001: /*
002: HttpdBase4J: An embeddable Java web server framework that supports HTTP, HTTPS,
003: templated content and serving content from inside a jar or archive.
004: Copyright (C) 2007 Donald Munro
005:
006: This library is free software; you can redistribute it and/or
007: modify it under the terms of the GNU Lesser General Public
008: License as published by the Free Software Foundation; either
009: version 2.1 of the License, or (at your option) any later version.
010:
011: This library is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: Lesser General Public License for more details.
015:
016: You should have received a copy of the GNU Lesser General Public
017: License along with this library; if not,see http://www.gnu.org/licenses/lgpl.txt
018: */
019:
020: package net.homeip.donaldm.httpdbase4j;
021:
022: import de.schlichtherle.io.File;
023: import java.io.FileNotFoundException;
024: import java.net.URL;
025: import java.net.URLClassLoader;
026:
027: import com.sun.net.httpserver.HttpHandler;
028: import java.lang.reflect.Method;
029:
030: /**
031: * Implementation of the abstract Httpd class for web content in a
032: * jar in the classpath or in an archive.
033: * @see Httpd
034: * @author Donald Munro
035: */
036: public class ArchiveHttpd extends Httpd implements HttpHandleable,
037: Postable
038: //=====================================================================
039: {
040: /**
041: * Compressed file containing web content. Prefarably jar but can also be
042: * zip, tar, tar.gz or tar.bz2
043: */
044: protected File m_archiveDirectory = null;
045:
046: protected java.io.File m_altFileSystemHome = null;
047:
048: /**
049: * Constructor with a home resource location. Assumes the content is in a jar
050: * in the classpath and will search the classpath to attempt to find the jar.
051: * @param homeDir The base directory in the jar where content is located
052: * @throws java.io.FileNotFoundException
053: */
054: public ArchiveHttpd(String homeDir) throws FileNotFoundException
055: //----------------------------------------------------------
056: {
057: super ();
058: m_archiveDirectory = findJarInCP(homeDir);
059: if (m_archiveDirectory == null)
060: throw new FileNotFoundException(homeDir
061: + " not found in classpath");
062: }
063:
064: /**
065: * Constructor with a jar file containing the resources and a home resource location
066: * within the jar.
067: * @param archiveFile A content jar, zip, tar, tar.gz or tar.bz2 file containing
068: * directory homeDir.
069: * @param archiveDirName The base directory in the content compressed file
070: * where content is located
071: * @throws java.io.FileNotFoundException
072: */
073: public ArchiveHttpd(java.io.File archiveFile, String archiveDirName)
074: throws FileNotFoundException
075: //---------------------------------------------------------------------------------
076: {
077: super ();
078: if ((archiveDirName == null)
079: || (archiveDirName.trim().length() == 0))
080: archiveDirName = "/";
081: archiveDirName = archiveDirName.trim();
082: m_archiveDirectory = new File(archiveFile, archiveDirName);
083: if (!m_archiveDirectory.exists())
084: throw new FileNotFoundException(archiveFile
085: .getAbsolutePath()
086: + " not found");
087: if ((archiveDirName.compareTo("/") != 0)
088: && (m_archiveDirectory.getEnclArchive() == null))
089: throw new FileNotFoundException(archiveDirName
090: + " not found in " + archiveFile.getName());
091: }
092:
093: /**
094: * Constructor with a home resource location and a thread model. Assumes the content is in a jar
095: * in the classpath and will search the classpath to attempt to find the jar.
096: * @param archiveDirName The base directory in the jar where content is located
097: * @param threadModel The thread model to use (SINGLE, MULTI or POOL)
098: */
099: public ArchiveHttpd(String archiveDirName, ThreadModel threadModel)
100: throws FileNotFoundException
101: //--------------------------------------------------------------
102: {
103: super ();
104: m_archiveDirectory = findJarInCP(archiveDirName);
105: m_threadModel = threadModel;
106: setDefaultPoolSizes();
107: }
108:
109: /**
110: * Constructor with a jar file, home resource location and a thread model
111: * @param archiveFile A content Jar file containing directory homeDir.
112: * @param archiveDirName The base directory in the jar where content is located
113: * @param threadModel The thread model to use (SINGLE, MULTI or POOL)
114: * @throws java.io.FileNotFoundException
115: */
116: public ArchiveHttpd(java.io.File archiveFile,
117: String archiveDirName, ThreadModel threadModel)
118: throws FileNotFoundException
119: //-------------------------------------------------------------------------
120: {
121: this (archiveFile, archiveDirName);
122: m_threadModel = threadModel;
123: setDefaultPoolSizes();
124: }
125:
126: /**
127: * Constructor for a fixed size thread pool based server. Assumes the content is in a jar
128: * in the classpath and will search the classpath to attempt to find the jar.
129: * @param archiveDirName The base directory in the jar where content is located
130: * @param poolSize Size of the thread pool
131: */
132: public ArchiveHttpd(String archiveDirName, int poolSize)
133: throws FileNotFoundException
134: //---------------------------------------------------
135: {
136: super ();
137: m_archiveDirectory = findJarInCP(archiveDirName);
138: m_threadModel = ThreadModel.POOL;
139: m_poolSize = poolSize;
140: m_poolMax = poolSize;
141: }
142:
143: /**
144: * Constructor for a thread pool based server. Assumes the content is in a jar
145: * in the classpath and will search the classpath to attempt to find the jar.
146: * @param archiveDirName The base directory in the jar where content is located
147: * @param poolSize Size of the thread pool
148: * @param maxPoolSize Maximum Size of the thread pool
149: */
150: public ArchiveHttpd(String archiveDirName, int poolSize,
151: int maxPoolSize) throws FileNotFoundException
152: //-----------------------------------------------------------------
153: {
154: super ();
155: m_archiveDirectory = findJarInCP(archiveDirName);
156: m_threadModel = ThreadModel.POOL;
157: m_poolSize = poolSize;
158: m_poolMax = maxPoolSize;
159: }
160:
161: /**
162: * Constructor for a thread pool based server.
163: * @param archiveFile A content Jar file containing directory homeDir.
164: * @param archiveDirName The base directory in the jar where content is located
165: * @param poolSize Size of the thread pool
166: * @param maxPoolSize Maximum Size of the thread pool
167: * @throws java.io.FileNotFoundException
168: */
169: public ArchiveHttpd(java.io.File archiveFile,
170: String archiveDirName, int poolSize, int maxPoolSize)
171: throws FileNotFoundException
172: //-------------------------------------------------------
173: {
174: this (archiveFile, archiveDirName);
175: m_threadModel = ThreadModel.POOL;
176: m_poolSize = poolSize;
177: m_poolMax = maxPoolSize;
178: }
179:
180: /**
181: * Get the directory within the archive for the base content.
182: * @return The directory within the archive for the base content.
183: */
184: public String getArchiveDirectoryName()
185: //---------------------------
186: {
187: return m_archiveDirectory.getInnerEntryName();
188: }
189:
190: /**
191: * Get the archive file for the base content.
192: * @return The archive file name for the base content.
193: */
194: public String getArchiveFileName()
195: //--------------------------
196: {
197: return m_archiveDirectory.getTopLevelArchive()
198: .getAbsolutePath();
199: }
200:
201: /**
202: * Get the archive file for the base content.
203: * @return The archive file for the base content.
204: */
205: public java.io.File getArchiveFile()
206: //--------------------------
207: {
208: if ((m_archiveDirectory != null)
209: && (m_archiveDirectory.getTopLevelArchive() != null))
210: return new File(m_archiveDirectory.getTopLevelArchive()
211: .getAbsolutePath());
212: return null;
213: }
214:
215: public void setJarDirectory(java.io.File archiveFile,
216: String archiveDirName) throws FileNotFoundException
217: //-----------------------------------------------------------------------
218: {
219: m_archiveDirectory = new de.schlichtherle.io.File(archiveFile,
220: archiveDirName);
221: if ((!m_archiveDirectory.exists())
222: || (!m_archiveDirectory.isArchive()))
223: throw new FileNotFoundException(archiveDirName
224: + " not found in " + archiveFile.getAbsolutePath());
225: }
226:
227: @Override
228: public String getHomePath() {
229: return m_archiveDirectory.getInnerEntryName();
230: }
231:
232: public void setAltFileSystemHome(java.io.File altHome)
233: //----------------------------------------------------
234: {
235: m_altFileSystemHome = altHome;
236:
237: }
238:
239: public java.io.File getAltFileSystemHome() {
240: return m_altFileSystemHome;
241: }
242:
243: @Override
244: protected HttpHandler onCreateRequestHandler()
245: //--------------------------------------------
246: {
247: ArchiveRequestHandler handler = new ArchiveRequestHandler(this ,
248: m_archiveDirectory, m_altFileSystemHome, m_isVerbose);
249: if (m_altFileSystemHome == null)
250: m_altFileSystemHome = handler.getAltFileSystemHome();
251: return handler;
252: }
253:
254: private File findJarInCP(String homeDir)
255: throws FileNotFoundException
256: //--------------------------------------------------------------------
257: {
258: ClassLoader sysClassLoader = ClassLoader.getSystemClassLoader();
259: URL[] urls = ((URLClassLoader) sysClassLoader).getURLs();
260: String[] jars = new String[urls.length];
261: for (int i = 0; i < urls.length; i++)
262: jars[i] = urls[i].getFile();
263: /* String cp = System.getProperty("java.class.path");
264: if ( (cp == null) || (cp.length() == 0) )
265: return null;
266: String[] jars = cp.split(File.pathSeparator);*/
267: for (int i = 0; i < jars.length; i++) {
268: String jar = jars[i];
269: if (jar == null)
270: continue;
271: jar = jar.trim();
272: if ((jar.length() == 0) || (jar.compareTo(".") == 0)
273: || (jar.compareTo("..") == 0))
274: continue;
275: File f = new File(jar);
276: if (!f.exists())
277: continue;
278: if ((f.isArchive()) || (f.isDirectory())) {
279: File home = new File(f, homeDir);
280: if (home.exists())
281: return home;
282: }
283: }
284: throw new FileNotFoundException(homeDir
285: + " not found in classpath");
286: }
287:
288: public static boolean addToClassPath(String jarFile)
289: throws FileNotFoundException
290: //---------------------------------------------------------------------------
291: {
292: java.io.File f = new java.io.File(jarFile);
293: if (!f.exists())
294: throw new FileNotFoundException(jarFile);
295: Class[] parameters = new Class[] { URL.class };
296: URLClassLoader sysloader = (URLClassLoader) ClassLoader
297: .getSystemClassLoader();
298: Class<URLClassLoader> sysclass = URLClassLoader.class;
299: //String urlPath = "jar:file://" + f.getAbsolutePath() + "!/";
300: try {
301: URL url = new URL("file://" + f.getAbsolutePath()
302: + ((f.isDirectory()) ? "/" : ""));
303: Method method = sysclass.getDeclaredMethod("addURL",
304: parameters);
305: method.setAccessible(true);
306:
307: method.invoke(sysloader, new Object[] { url });
308: } catch (Throwable t) {
309: t.printStackTrace();
310: return false;
311: }
312: return true;
313: }
314:
315: public static boolean isInClassPath(String jarFileName)
316: //-----------------------------------------------------
317: {
318: ClassLoader sysClassLoader = ClassLoader.getSystemClassLoader();
319: URL[] urls = ((URLClassLoader) sysClassLoader).getURLs();
320: for (int i = 0; i < urls.length; i++) {
321: java.io.File jarInPath = new java.io.File(urls[i].getFile());
322: java.io.File jarFile = new java.io.File(jarFileName);
323: System.out.println(jarFile.getName() + " "
324: + jarInPath.getName());
325: if (jarFile.getName().compareTo(jarInPath.getName()) == 0)
326: return true;
327: }
328: return false;
329: }
330:
331: public static String getClasspath()
332: //-----------------------------
333: {
334: ClassLoader sysClassLoader = ClassLoader.getSystemClassLoader();
335: URL[] urls = ((URLClassLoader) sysClassLoader).getURLs();
336: StringBuffer sb = new StringBuffer();
337: for (int i = 0; i < urls.length; i++) {
338: sb.append(urls[i].getFile());
339: sb.append(':');
340: }
341: return sb.toString();
342: }
343: }
|