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 java.io.IOException;
023: import java.io.InputStream;
024: import java.io.UnsupportedEncodingException;
025: import java.util.ArrayList;
026: import java.util.Date;
027:
028: import com.sun.net.httpserver.HttpExchange;
029:
030: import de.schlichtherle.io.File;
031: import de.schlichtherle.io.FileInputStream;
032:
033: /**
034: * <p>
035: * Support for combining several style sheets or javascripts for archive or classpath
036: * based requests into one request.
037: * For example the client could specify:
038: * </p><br>
039: * <code>
040: * <link rel="stylesheet" type="text/css" media="all" href="styles/1.css,2.css,
041: * morestyles/3.css" />
042: * </code>
043: * <p>
044: * Different stylesheets/scripts are separated by commas; if the stylesheet name
045: * includes a / then it is assumed to be a full directory name otherwise it
046: * uses the previous entries directory. If the previoud directory did not have
047: * a directory then / is assumed eg
048: * </p><br>
049: * <code>
050: * <script type="text/javascript" src="1.js,2.js,3.js">
051: * </code><br>
052: * * 1.js, 2.js and 3.js are assumed to be in /.<br>
053: * <p>
054: * <b>This is non-standard HTML</b>, although it can be done in for example
055: * Apache using rewriting and server side scripts.
056: * (@see http://rakaz.nl/item/make_your_pages_load_faster_by_combining_and_compressing_javascript_and_css_files)
057: * </p>
058: * @author Donald Munro
059: */
060: public class ArchiveCombinedRequest extends CombinedRequest implements
061: Cloneable
062: //============================================================================
063: {
064:
065: /**
066: * The base directory containing the resource
067: */
068: protected File m_homeDir = null;
069:
070: /**
071: * Array of full paths of the resource.
072: */
073: protected ArrayList<File> m_requestFiles = new ArrayList<File>();
074:
075: /**
076: * Create an ArchiveCombinedRequest.
077: * @param httpd The Httpd instance
078: * @param ex The HttpExchange instance for this HTTP transaction
079: * @param homeDir Directory in archive where combined request files
080: * reside.
081: * @throws UnsupportedEncodingException
082: * @throws IOException
083: */
084: protected ArchiveCombinedRequest(Httpd httpd, HttpExchange ex,
085: File homeDir) throws UnsupportedEncodingException,
086: IOException
087: //---------------------------------------------------------------------
088: {
089: super (httpd, ex);
090: m_homeDir = homeDir;
091: splitUp();
092: }
093:
094: /**
095: * Add a file to the list of files for this CombinedRequest
096: */
097: protected void addFile(String file)
098: //---------------------------------
099: {
100: m_requestFiles.add(new File(m_homeDir, file));
101: }
102:
103: /**
104: * @return true if all the files in the combined request exist.
105: */
106: @Override
107: public boolean exists()
108: //---------------------
109: {
110: for (int i = 0; i < m_requestFiles.size(); i++) {
111: if (!m_requestFiles.get(i).exists()) {
112: if (m_strict)
113: return false;
114: } else
115: return true;
116: }
117: return false;
118: }
119:
120: @Override
121: public boolean isReadable() {
122: return this .exists();
123: }
124:
125: /**
126: * @return The maximum date of all the files in the combined
127: * request
128: */
129: @Override
130: public Date getDate()
131: //-------------------
132: {
133: long maxt = 0;
134: for (int i = 0; i < m_requestFiles.size(); i++) {
135: File f = m_requestFiles.get(i);
136: long t = f.lastModified();
137: if (t > maxt)
138: maxt = t;
139: }
140: return new Date(maxt);
141: }
142:
143: /**
144: * @inheritDoc
145: */
146: @Override
147: public String getName()
148: //--------------------
149: {
150: StringBuffer names = new StringBuffer();
151: for (int i = 0; i < m_requestFiles.size(); i++) {
152: File f = new File(m_requestFiles.get(i).getInnerEntryName());
153: String name = f.getName();
154: if (names.length() > 0) {
155: names.append(name);
156: names.append(m_delimiter);
157: }
158: }
159: return names.toString();
160: }
161:
162: /**
163: * @inheritDoc
164: */
165: @Override
166: public String getETag(boolean refresh)
167: //---------------------
168: {
169: if ((!refresh) && (m_eTag != null))
170: return m_eTag;
171: DirItemInterface[] items = new DirItemInterface[m_requestFiles
172: .size()];
173: for (int i = 0; i < m_requestFiles.size(); i++)
174: items[i] = new ArchiveRequest.DirItem(m_requestFiles.get(i));
175: m_eTag = Http.eTag(items);
176: return m_eTag;
177: }
178:
179: /**
180: * @return The number of files in the combined request
181: */
182: protected int getCount() {
183: return m_requestFiles.size();
184: }
185:
186: /**
187: * @param i Index of the file for which to return an InputStream.
188: * @return An InputStream for the <i>i</i>th file in the combined request
189: */
190: protected InputStream getItemStream(int i)
191: //----------------------------------------
192: {
193: try {
194: return new FileInputStream(m_requestFiles.get(i));
195: } catch (Exception e) {
196: return null;
197: }
198: }
199: }
|