001: // ToolsListerFrame.java
002: // $Id: ToolsListerFrame.java,v 1.12 2007/02/10 12:50:34 ylafon Exp $
003: // (c) COPYRIGHT MIT and INRIA, 1998.
004: // Please first read the full copyright statement in file COPYRIGHT.html
005:
006: package org.w3c.jigedit.tools;
007:
008: import java.io.File;
009: import java.io.PrintStream;
010:
011: import java.text.SimpleDateFormat;
012:
013: import java.util.Date;
014: import java.util.Enumeration;
015: import java.util.TimeZone;
016: import java.util.Vector;
017:
018: import org.w3c.tools.resources.AbstractContainer;
019: import org.w3c.tools.resources.DirectoryResource;
020: import org.w3c.tools.resources.FramedResource;
021: import org.w3c.tools.resources.InvalidResourceException;
022: import org.w3c.tools.resources.ProtocolException;
023: import org.w3c.tools.resources.Resource;
024: import org.w3c.tools.resources.ResourceException;
025: import org.w3c.tools.resources.ResourceFrame;
026: import org.w3c.tools.resources.ResourceReference;
027:
028: import org.w3c.tools.sorter.Sorter;
029:
030: import org.w3c.jigsaw.forms.URLDecoder;
031:
032: import org.w3c.jigsaw.http.HTTPException;
033: import org.w3c.jigsaw.http.Reply;
034: import org.w3c.jigsaw.http.Request;
035:
036: import org.w3c.jigsaw.html.HtmlGenerator;
037:
038: import org.w3c.jigsaw.frames.HTTPFrame;
039: import org.w3c.jigsaw.frames.PostableFrame;
040:
041: import org.w3c.jigedit.cvs.CvsFrame;
042:
043: import org.w3c.www.http.HTTP;
044: import org.w3c.www.http.HttpEntityMessage;
045: import org.w3c.www.http.HttpRequestMessage;
046:
047: import org.w3c.tools.resources.event.StructureChangedEvent;
048: import org.w3c.tools.resources.event.StructureChangedListener;
049:
050: /**
051: * Emit the content of its parent directory.
052: */
053: public class ToolsListerFrame extends PostableFrame implements
054: StructureChangedListener {
055: private static final boolean debug = true;
056:
057: private boolean invalid = true;
058:
059: private ResourceReference dirResourceRef = null;
060:
061: protected ResourceReference getDirResourceRef() {
062: if (invalid || (dirResourceRef == null)) {
063: dirResourceRef = getResource().getParent();
064: }
065: return dirResourceRef;
066: }
067:
068: public void registerResource(FramedResource resource) {
069: super .registerOtherResource(resource);
070: dirResourceRef = resource.getParent();
071: try {
072: FramedResource fres = (FramedResource) dirResourceRef
073: .lock();
074: // register us as a listener
075: fres.addStructureChangedListener(this );
076: } catch (InvalidResourceException ex) {
077: ex.printStackTrace();
078: } finally {
079: dirResourceRef.unlock();
080: }
081: invalid = false;
082: }
083:
084: /**
085: * Unused here.
086: */
087: public void resourceModified(StructureChangedEvent evt) {
088: }
089:
090: /**
091: * Unused here.
092: */
093: public void resourceCreated(StructureChangedEvent evt) {
094: }
095:
096: public void resourceUnloaded(StructureChangedEvent evt) {
097: }
098:
099: /**
100: * A resource is about to be removed
101: * This handles the <code>RESOURCE_REMOVED</code> kind of events.
102: * @param evt The event describing the change.
103: */
104:
105: public void resourceRemoved(StructureChangedEvent evt) {
106: invalid = true;
107: }
108:
109: protected Class httpClass = null;
110:
111: private String getResourceLine(ResourceReference rr, String name,
112: boolean even) {
113: if (httpClass == null) {
114: try {
115: httpClass = Class
116: .forName("org.w3c.jigsaw.frames.HTTPFrame");
117: } catch (ClassNotFoundException ex) {
118: httpClass = null;
119: }
120: }
121: // get the right date formatter
122: SimpleDateFormat df;
123: df = new SimpleDateFormat("yyyy MMM dd - HH:mm:ss zzz");
124: df.setTimeZone(TimeZone.getTimeZone("GMT"));
125:
126: StringBuffer buffer = new StringBuffer(100);
127: try {
128: FramedResource resource = (FramedResource) rr.lock();
129: if (name == null)
130: name = resource.getIdentifier();
131: if (even) {
132: buffer.append("<tr class=\"evenlist\" align=\"left\" "
133: + "valign=\"bottom\">");
134: } else {
135: buffer.append("<tr class=\"oddlist\" align=\"left\" "
136: + "valign=\"bottom\">");
137: }
138: HTTPFrame itsframe = null;
139: if (httpClass != null)
140: itsframe = (HTTPFrame) resource.getFrame(httpClass);
141: if (itsframe instanceof CvsFrame) {
142: buffer.append("<td></td>");
143: } else {
144: buffer.append("<td>");
145: buffer.append("<INPUT TYPE=\"CHECKBOX\" NAME=\"" + name
146: + "\"> ");
147: buffer.append("</td>");
148: }
149: buffer.append("<td>");
150: if (itsframe != null) {
151: String icon = itsframe.getIcon();
152: if (icon != null)
153: buffer.append("<IMG SRC=\"" + getIconDirectory()
154: + "/" + icon + "\">");
155: // Resource's name with link:
156: buffer.append("<A HREF=\"" + resource.getURLPath()
157: + "\">" + name + "</A>");
158: // resource's title, if any:
159: String title = itsframe.getTitle();
160: if (title != null) {
161: buffer.append("</td><td>" + title);
162: } else {
163: buffer.append("</td><td>");
164: }
165: int clength = itsframe.getContentLength();
166: if (clength != -1) {
167: int kcl = clength / 1024;
168: buffer.append("</td><td>[ " + kcl + " kB ]");
169: } else {
170: buffer.append("</td><td>-");
171: }
172: long clm = itsframe.getLastModified();
173: if (clm != -1) {
174: buffer.append("</td><td>"
175: + df.format(new Date(clm)));
176: } else {
177: buffer.append("</td><td>-");
178: }
179: } else {
180: // Resource's name with link:
181: buffer.append("<A HREF=\"" + resource.getURLPath()
182: + "\">" + name + "</A>"
183: + " Not available via HTTP");
184: buffer.append("</td><td></td><td></td><td>\n");
185: }
186: buffer.append("</td></tr>\n");
187: } catch (InvalidResourceException ex) {
188: buffer.append("<td> " + name);
189: buffer.append("cannot be loaded (server misconfigured)");
190: buffer.append("<BR>");
191: buffer.append("</td></tr>\n");
192: } finally {
193: rr.unlock();
194: }
195: return buffer.toString();
196: }
197:
198: /**
199: * Get the directory listing.
200: * @param request the incomming request.
201: * @exception ProtocolException if a protocol error occurs
202: * @exception ResourceException if a server error occurs
203: */
204: public synchronized Reply getDirectoryListing(Request request)
205: throws ProtocolException, ResourceException {
206: DirectoryResource dirResource = null;
207: try {
208: dirResource = (DirectoryResource) getDirResourceRef()
209: .lock();
210: if (dirResource == null)
211: throw new ResourceException("parent is NOT a "
212: + "DirectoryResource. ("
213: + resource.getIdentifier() + ")");
214: if (!dirResource.verify()) {
215: // the directory was deleted, but we can't delete it here
216: // (Multiple Locks)
217: // Emit an error back:
218: Reply error = request.makeReply(HTTP.NOT_FOUND);
219: error.setContent("<h1>Document not found</h1>"
220: + "<p>The document " + request.getURL()
221: + " is indexed but not available."
222: + "<p>The server is misconfigured.");
223: throw new HTTPException(error);
224: }
225: // Have we already an up-to-date computed a listing ?
226: if ((listing == null)
227: || (dirResource.getDirectory().lastModified() > listing_stamp)
228: || (dirResource.getLastModified() > listing_stamp)
229: || (getLastModified() > listing_stamp)) {
230:
231: Enumeration e = dirResource
232: .enumerateResourceIdentifiers();
233: Vector resources = Sorter.sortStringEnumeration(e);
234: HtmlGenerator g = new HtmlGenerator(
235: "Directory listing of "
236: + dirResource.getIdentifier());
237: // Add style link
238: addStyleSheet(g);
239: g.append("<h1>Directory listing of ", dirResource
240: .getIdentifier(), "</h1>");
241: // Link to the parent, when possible:
242: if (dirResource.getParent() != null)
243: g.append("<p><a href=\"..\">Parent</a><br>");
244: g.append("\n<form method=\"POST\" action=\""
245: + request.getURL() + "\">\n");
246: String listername = getResource().getIdentifier();
247: // List the children:
248: g.append("<table border=\"0\">\n");
249:
250: ResourceReference rr = null;
251: FramedResource resource = null;
252: String name = null;
253: //ugly hack to put CVS link first
254: rr = dirResource.lookup("CVS");
255: if (rr != null) {
256: g.append(getResourceLine(rr, "CVS", false));
257: }
258: boolean even = true;
259: for (int i = 0; i < resources.size(); i++) {
260: name = (String) resources.elementAt(i);
261: if (name.equals(listername) || name.equals("CVS"))
262: continue;
263: rr = dirResource.lookup(name);
264: g.append(getResourceLine(rr, name, even));
265: even = !even;
266: }
267: g.append("</table>\n");
268: g
269: .append("<P><INPUT TYPE=\"SUBMIT\" NAME=\"SUBMIT\" VALUE=\""
270: + "Delete file from publishing space\"></FORM>\n");
271: g.close();
272: listing_stamp = getLastModified();
273: listing = g;
274: } else if (checkIfModifiedSince(request) == COND_FAILED) {
275: // Is it an IMS request ?
276: return createDefaultReply(request, HTTP.NOT_MODIFIED);
277: }
278: } catch (InvalidResourceException ex) {
279: return createDefaultReply(request,
280: HTTP.INTERNAL_SERVER_ERROR);
281: } finally {
282: getDirResourceRef().unlock();
283: }
284: // New content or need update:
285: Reply reply = createDefaultReply(request, HTTP.OK);
286: reply.setLastModified(listing_stamp);
287: reply.setStream(listing);
288: return reply;
289: }
290:
291: /**
292: * @exception org.w3c.tools.resources.ProtocolException
293: * if a protocol error occurs
294: * @exception org.w3c.tools.resources.ResourceException
295: * if a server error occurs
296: */
297: protected Reply getOtherResource(Request request)
298: throws ProtocolException, ResourceException {
299: return getDirectoryListing(request);
300: }
301:
302: /**
303: * Handle the form submission, after posted data parsing.
304: * <p>This method ought to be abstract, but for reasonable reason, it
305: * will just dump (parsed) the form content back to the client, so that it
306: * can be used for debugging.
307: * @param request The request proper.
308: * @param data The parsed data content.
309: * @exception ProtocolException If form data processing failed.
310: * @see org.w3c.jigsaw.forms.URLDecoder
311: */
312:
313: public Reply handle(Request request, URLDecoder data)
314: throws ProtocolException {
315: Reply r;
316: Enumeration e = data.keys();
317: while (e.hasMoreElements()) {
318: String name = (String) e.nextElement();
319: if (name.equals("SUBMIT"))
320: continue;
321: // delete file now... avoit deleting CVS and lister
322: // (should be in an attribute)
323: synchronized (this ) {
324: DirectoryResource dr;
325: Resource toDeleteRes;
326: ResourceReference rr;
327: File dir, toDeleteFile;
328: try {
329: dr = (DirectoryResource) getDirResourceRef().lock();
330: dir = dr.getDirectory();
331: if (debug)
332: System.out.println("Deleting " + name);
333: rr = dr.lookup(name);
334: if (rr != null) {
335: try {
336: toDeleteFile = new File(dir, name);
337: toDeleteFile.delete();
338: } catch (Exception ex) {
339: // fancy message. file not present
340: // Or security manager forbiding deletion.
341: }
342: // and now, at least remove the resource
343: try {
344: toDeleteRes = (Resource) rr.lock();
345: toDeleteRes.delete();
346: } catch (Exception ex) {
347: // some other locks... or pb with the resource
348: } finally {
349: rr.unlock();
350: }
351: }
352: } catch (Exception ex) {
353: // some other locks... abort
354: } finally {
355: getDirResourceRef().unlock();
356: }
357: }
358: }
359: try {
360: r = getDirectoryListing(request);
361: } catch (ResourceException ex) {
362: r = createDefaultReply(request, HTTP.INTERNAL_SERVER_ERROR);
363: }
364: return r;
365: }
366: }
|