View Javadoc
1   /**
2    * Copyright By Grandsoft Company Limited.  
3    * 2012-1-16 下午02:18:02
4    */
5   package gboat2.base.core;
6   
7   import gboat2.base.core.service.ModuleService;
8   import gboat2.base.core.util.SpringContextUtil;
9   import gboat2.base.core.validate.PrivilegeCheckServiceFactory;
10  import gboat2.base.core.web.SystemButtonProviderTracker;
11  
12  import java.io.File;
13  import java.io.FileFilter;
14  import java.io.FileInputStream;
15  import java.io.IOException;
16  import java.io.InputStream;
17  import java.util.ArrayList;
18  import java.util.HashMap;
19  import java.util.List;
20  import java.util.Map;
21  import java.util.jar.JarFile;
22  import java.util.zip.ZipEntry;
23  
24  import javax.xml.parsers.DocumentBuilder;
25  import javax.xml.parsers.DocumentBuilderFactory;
26  import javax.xml.parsers.ParserConfigurationException;
27  
28  import org.apache.commons.lang3.StringUtils;
29  import org.osgi.framework.Bundle;
30  import org.osgi.framework.BundleActivator;
31  import org.osgi.framework.BundleContext;
32  import org.osgi.framework.BundleEvent;
33  import org.osgi.framework.BundleListener;
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  import org.w3c.dom.Document;
37  import org.w3c.dom.Element;
38  import org.w3c.dom.NodeList;
39  import org.xml.sax.SAXException;
40  
41  /**
42   * 
43   * gboat2.base.core的Activator
44   * @author lysming
45   * @since jdk1.6
46   * @date 2012-1-16
47   *  
48   */
49  
50  public class Activator implements BundleActivator, BundleListener {
51  	
52  	private static Logger logger = LoggerFactory.getLogger(Activator.class);
53  	
54  	public static Bundle LOCAL_BUNDLE;
55  	
56  	private static final String HEADER_STRUTS_ENABLED = "Struts2-Enabled";
57  	
58  	// true 为项目bundle, false 为产品bundle
59  	public static final String HEADER_PROJECT_ENABLED = "Project-Enabled";
60  	
61  	// 扩展的bundles,多个用逗号隔开
62  	public static final String HEADER_EXTENDER_BUNDLES = "Extend-Bundles";
63  	
64  	public static Map<String, Map<String, String>> pomCache = new HashMap<String, Map<String, String>>();
65  	
66  	/** 
67  	  * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)   
68  	  * @param context BundleContext对象
69  	  * @throws Exception felix异常
70  	  */
71  	public void start(BundleContext context) throws Exception {
72  		LOCAL_BUNDLE = context.getBundle();
73  		
74  		context.addBundleListener(this);
75  		context.addBundleListener(SpringContextUtil.getInstance());
76  		//处理在该Bundle启动之前已经启动的Bundle
77  		Bundle[] allBundles = context.getBundles();
78  		GBoatClassLoader loader = GBoatClassLoader.getInstance();
79  		for (Bundle tempBnd : allBundles) {
80  			String seTag = (String) tempBnd.getHeaders().get(HEADER_STRUTS_ENABLED);
81  			if (seTag != null && seTag.equals("true") && Bundle.ACTIVE == tempBnd.getState()) {
82  				registBundle(tempBnd, loader);
83  			}
84  			
85  			// 读取pom.xml项目扩展参数
86  			Map<String, String> value = new HashMap<String, String>();
87  			String project = tempBnd.getHeaders().get(HEADER_PROJECT_ENABLED);
88  			if (StringUtils.isEmpty(project)) continue;
89  			String bundles = tempBnd.getHeaders().get(HEADER_EXTENDER_BUNDLES);
90  			value.put(HEADER_PROJECT_ENABLED, project);
91  			value.put(HEADER_EXTENDER_BUNDLES, bundles);
92  
93  			pomCache.put(tempBnd.getSymbolicName(), value);
94  		}
95  	}
96  	
97  	public void stop(BundleContext context) throws Exception {
98  		context.removeBundleListener(this);
99  		PrivilegeCheckServiceFactory.close();
100 		SystemButtonProviderTracker.close();
101 	}
102 	
103 	public void bundleChanged(BundleEvent event) {
104 		GBoatClassLoader loader = GBoatClassLoader.getInstance();
105 		if (event.getType() == BundleEvent.STARTED) {
106 			Bundle bundle = event.getBundle();
107 			String seTag = (String) bundle.getHeaders().get(HEADER_STRUTS_ENABLED);
108 			if (seTag != null && seTag.equals("true")) {
109 				registBundle(bundle, loader);
110 			}
111 		}
112 		//清空SpringContextUtil中的ApplicationContext,否则重启后无法设置
113 		if ((event.getType() & BundleEvent.STOPPED) != 0) {
114 			ModuleService.unRegistModule(event.getBundle());
115 		}
116 	}
117 	
118 	//注册Struts类型的Bundle,解析所有该Bundle下Action的Module
119 	private void registBundle(Bundle bundle, GBoatClassLoader loader) {
120 		List<String> pkgForBundle = getPkgForBundle(bundle);
121 		for (String tempPkg : pkgForBundle) {
122 			loader.add(tempPkg, bundle);
123 			ModuleService.registModule(tempPkg);
124 		}
125 	}
126 	
127 	/**
128 	 * 取出某个Bundle下所有Action的package
129 	 * @param bundle bundle对象
130 	 * @return 该Bundle下Action的package
131 	 */
132 	private List<String> getPkgForBundle(Bundle bundle) {
133 		List<String> pkgList = new ArrayList<String>();
134 		try {
135 			logger.debug("register actions for " + bundle.getSymbolicName() + " ...");
136 			if (bundle.getLocation().startsWith("file:")) {
137 				JarFile file = new JarFile(bundle.getLocation().replaceFirst("file:[/|\\\\]", ""));
138 				
139 				ZipEntry entry = file.getEntry("struts.xml");
140 				if (entry != null) {
141 					parseActionPackages(file.getInputStream(entry), pkgList);
142 				} else {
143 					logger.debug("no struts.xml found.");
144 				}
145 			} else if (bundle.getLocation().startsWith("jardir:")) {//自动部署工具安装的bundle
146 				File dir = new File(bundle.getLocation().replaceFirst("jardir:", ""));
147 				if (dir.isDirectory()) {
148 					File[] configFiles = dir.listFiles(new FileFilter() {
149 						
150 						@Override
151 						public boolean accept(File pathname) {
152 							if (pathname.getName().equals("struts.xml")) {
153 								return true;
154 							}
155 							return false;
156 						}
157 					});
158 					if (configFiles.length == 0) {
159 						logger.debug("no struts.xml found.");
160 					} else {
161 						File strutsConfig = configFiles[0];
162 						FileInputStream is = new FileInputStream(strutsConfig);
163 						parseActionPackages(is, pkgList);
164 					}
165 				} else {
166 					logger.debug(bundle.getLocation() + " is not a direction");
167 				}
168 			}
169 		} catch (IOException e) {
170 			e.printStackTrace();
171 		}
172 		return pkgList;
173 	}
174 	
175 	private void parseActionPackages(InputStream io, List<String> pkgList) {
176 		try {
177 			DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
178 			domFactory.setValidating(false);
179 			domFactory.setNamespaceAware(true); // never forget this!
180 			DocumentBuilder builder = domFactory.newDocumentBuilder();
181 			
182 			Document doc = builder.parse(io);
183 			NodeList ns = doc.getElementsByTagName("constant");
184 			Element element;
185 			for (int i = 0; i < ns.getLength(); i++) {
186 				element = (Element) ns.item(i);
187 				if (element.getAttribute("name").equals("struts.convention.package.locators.basePackage")) {
188 					String pkg = element.getAttribute("value");
189 					logger.debug("packages defined in struts.xml is " + pkg);
190 					/**
191 					 * 修改Struts 注册 constant 的action package 方法:
192 					 * 用","分割,可以注册多个action 包
193 					 * modify by wanghb
194 					 */
195 					if (StringUtils.isNotEmpty(pkg)) {
196 						String[] pkgs = pkg.split(",");
197 						for(String pkgStr : pkgs) {
198 							pkgStr = pkgStr.trim();
199 							if (StringUtils.isNotEmpty(pkgStr)) {
200 								pkgList.add(pkgStr);
201 							}
202 						}
203 					}
204 					break;
205 				}
206 			}
207 		} catch (ParserConfigurationException e) {
208 			logger.error(e.getMessage(), e);
209 		} catch (SAXException e) {
210 			logger.error(e.getMessage(), e);
211 		} catch (IOException e) {
212 			logger.error(e.getMessage(), e);
213 		}
214 	}
215 	
216 }