View Javadoc

1   /*
2    *  
3    *  Fosstrak LLRP Commander (www.fosstrak.org)
4    * 
5    *  Copyright (C) 2008 ETH Zurich
6    *
7    *  This program is free software: you can redistribute it and/or modify
8    *  it under the terms of the GNU General Public License as published by
9    *  the Free Software Foundation, either version 3 of the License, or
10   *  (at your option) any later version.
11   *
12   *  This program is distributed in the hope that it will be useful,
13   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   *  GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License
18   *  along with this program.  If not, see <http://www.gnu.org/licenses/> 
19   *
20   */
21  
22  package org.fosstrak.capturingapp;
23  
24  import java.io.IOException;
25  import java.lang.reflect.Constructor;
26  import java.util.Map;
27  import java.util.Properties;
28  import java.util.concurrent.ConcurrentHashMap;
29  import java.util.concurrent.ExecutorService;
30  import java.util.concurrent.Future;
31  
32  import org.apache.log4j.Logger;
33  import org.fosstrak.capturingapp.util.CaptureAppWorker;
34  import org.fosstrak.capturingapp.wsdl.ArrayOfString;
35  import org.fosstrak.capturingapp.wsdl.CaptureAppPortType;
36  import org.fosstrak.capturingapp.wsdl.EmptyParms;
37  
38  
39  /**
40   * entry point for the Fosstrak capturing application service. the service has been 
41   * implemented as a fully blown WS-service. Therefore if someone likes to 
42   * implement the service with an interface providing creation, deletion and 
43   * modification of capture applications, feel free to go ahead...<br/>
44   * The service currently exports the names of the capture applications. 
45   * @author sawielan
46   *
47   */
48  public class CaptureAppPortTypeImpl implements CaptureAppPortType {
49  
50  	// the executor thread pool.
51  	private static ExecutorService pool = java.util.concurrent.
52  			Executors.newCachedThreadPool();
53  	
54  	// a hash map maintaining the different capture applications.
55  	private static Map<String, CaptureAppWorker> captureApps = new ConcurrentHashMap<String, CaptureAppWorker> ();
56  	
57  	// logger.
58      private static final Logger log = Logger.getLogger(CaptureAppPortTypeImpl.class);
59  
60      /** the name of the configuration file. */
61      public static final String CONFIG_FILE = "/captureapplication.properties";
62      
63      /** the class name of the default handler. */
64      public static final String DEFAULT_HANDLER_CLASS_NAME = 
65      	"org.fosstrak.capturingapp.DefaultECReportHandler";
66      
67      // flag whether the capture app is initialized or not.
68      private static boolean initialized = false;
69      
70      /**
71       * create a new capture application port type.
72       * @throws Exception upon some exception.
73       */
74      public CaptureAppPortTypeImpl() throws Exception {
75      	initialize();
76      }
77      
78      /**
79       * submit a runnable to the thread pool and execute it.
80       * @param runnable the runnable to execute.
81       * @return a future value with a handle on the executor.
82       */
83      @SuppressWarnings("unchecked")
84  	public static Future submitToThreadPool(Runnable runnable) {
85      	return pool.submit(runnable);
86      	
87      }
88      
89      /**
90       * initialize the WS.
91       * @throws Exception when the configuration file could not be found or 
92       * if there is an error in the configuration.
93       */
94      private static void initialize() throws Exception {
95      	if (initialized) {
96      		log.error("already initialized.");
97      		return;
98      	}
99      	
100     	log.info("initialize capture applications");
101     	
102     	Properties props = new Properties();
103     	try {
104 			props.load(
105 					CaptureAppPortTypeImpl.class.getResourceAsStream(
106 							CONFIG_FILE));
107 			
108 			final int n = Integer.parseInt(props.getProperty("n"));
109 			// create capture apps for all the configurations...
110 			for (int i = 0; i<n; i++) {
111 				
112 				final int port = Integer.parseInt(
113 						props.getProperty("cap." + i + ".port", "-1"));
114 				
115 				final String name = props.getProperty(
116 						"cap." + i + ".name", "cap." + i + ".name");
117 				
118 				final String epcis = props.getProperty(
119 						"cap." + i + ".epcis", "tcp://localhost:1234");	
120 				
121 				final String changeSet = props.getProperty(
122 						"cap." + i + ".changeset", null);
123 				
124 				String handlerClzzName = props.getProperty(
125 						"cap." + i + ".handler", null);
126 				
127 				log.info(String.format("create new capture app: (%s,%d,%s)",
128 						name, port, epcis));
129 				captureApps.put(name, new CaptureAppWorker(
130 						name,
131 						new org.fosstrak.capturingapp.CaptureApp(port,
132 							epcis)));
133 				
134 				if (null == handlerClzzName) {
135 					handlerClzzName = DEFAULT_HANDLER_CLASS_NAME;
136 				}
137 				log.info("Using handler class: " + handlerClzzName);
138 				
139 				try {
140 					Class cls = Class.forName(handlerClzzName); 
141 					Object obj = null;
142 					if (null == changeSet) {
143 						obj = cls.newInstance();
144 					} else {
145 						log.debug(String.format("using changeSet: %s", changeSet));
146 						Constructor ctor = cls.getConstructor(String.class);
147 						obj = ctor.newInstance(changeSet);
148 					}
149 					
150 					if (obj instanceof ECReportsHandler) {
151 						captureApps.get(name).getCaptureApp().
152 							registerHandler((ECReportsHandler)obj);
153 						 
154 					} else {
155 						throw new Exception("Invalid type: " + obj.getClass());
156 					}					
157 				} catch (Exception e) {
158 					log.error("Could not create handler: " + e.getMessage());
159 				}
160 			}
161 			
162 			// start the capture apps
163 			for (CaptureAppWorker worker : captureApps.values()) {
164 				log.info(String.format("starting capture app: (%s,%d,%s)",
165 						worker.getIdentifier(), 
166 						worker.getCaptureApp().getPort(),
167 						worker.getCaptureApp().getEpcisRepositoryURL()));
168 				worker.start();
169 			}
170 			
171 		} catch (IOException e) {
172 			log.error("could not load config file - aborting.");
173 			e.printStackTrace();
174 			initialized = false;
175 			throw e;
176 		}
177     	
178     	initialized = true;
179     }
180 
181     // --------- \\ WS definition
182     
183     /* (non-Javadoc)
184      * @see org.fosstrak.captureapp.wsdl.CaptureAppPortType#getCaptureAppNames(org.fosstrak.captureapp.wsdl.EmptyParms  parms )*
185      */
186     public org.fosstrak.capturingapp.wsdl.ArrayOfString getCaptureAppNames(EmptyParms parms)  {
187     	ArrayOfString aos = new ArrayOfString();
188     	for (CaptureAppWorker worker : captureApps.values()) {
189     		aos.getString().add(worker.getIdentifier());
190     	}
191     	return aos;
192     }
193     
194     // --------- \\ end of WS definition
195     
196     protected void finalize() throws Throwable {
197     	log.info("finalizer called.");
198     	for (CaptureAppWorker worker : captureApps.values()) {
199     		worker.stop();
200     	}
201     	super.finalize();
202     } 
203 
204 }