Java tutorial
/* Copyright (C) 2007 Helge Hess This file is part of JOPE. JOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. JOPE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with JOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.getobjects.appserver.publisher; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.getobjects.appserver.core.WOContext; import org.getobjects.appserver.core.WOElement; import org.getobjects.appserver.core.WOMessage; import org.getobjects.appserver.core.WOResponse; /** * JoResource * <p> * This JoObject takes a URL and delivers its contents as a resource. Eg its * used by JoProduct to deliver public product resources. * <p> * Note: this object supports nested queries. Eg /www/images/myimage.gif. */ public class JoResource extends WOElement implements IJoObject { protected static final Log log = LogFactory.getLog("JoResource"); protected URL url; public JoResource(URL _url) { this.url = _url; } /* generate response */ public static String mimeTypeForPath(String _path) { // TODO: fix this crap and use some real MIME/ext object int idx = _path.lastIndexOf('.'); if (idx < 0) { log.error("could not detect MIME type for path: " + _path); return null; } String mimeType = null; String ext = _path.substring(idx + 1); if (ext.equals("css")) mimeType = "text/css"; else if (ext.equals("txt")) mimeType = "text/plain"; else if (ext.equals("js")) mimeType = "text/javascript"; else if (ext.equals("gif")) mimeType = "image/gif"; else if (ext.equals("png")) mimeType = "image/png"; else if (ext.equals("jpg") || ext.equals("jpeg")) mimeType = "image/jpeg"; else if (ext.equals("html")) mimeType = "text/html"; else log.error("MIME type unknown for extension '" + ext + "': " + _path); return mimeType; } protected int expirationIntervalForMimeType(String _mimeType) { return 3600 /* 1 hour */; } @Override public void appendToResponse(WOResponse _r, WOContext _ctx) { URLConnection con = null; try { con = this.url.openConnection(); } catch (IOException coe) { log.warn("could not open connection to url: " + this.url); _r.setStatus(WOMessage.HTTP_STATUS_NOT_FOUND); return; } /* open stream */ InputStream is = null; try { is = con.getInputStream(); } catch (IOException ioe) { log.warn("could not open stream to url: " + this.url); _r.setStatus(WOMessage.HTTP_STATUS_NOT_FOUND); return; } /* transfer */ try { String mimeType = con.getContentType(); if (mimeType == null || "content/unknown".equals(mimeType)) mimeType = mimeTypeForPath(this.url.getPath()); if (mimeType == null) mimeType = "application/octet-stream"; _r.setHeaderForKey(mimeType, "content-type"); _r.setHeaderForKey("" + con.getContentLength(), "content-length"); /* setup caching headers */ Date now = new Date(); GregorianCalendar cal = new GregorianCalendar(); cal.setTime(new Date(con.getLastModified())); _r.setHeaderForKey(WOMessage.httpFormatDate(cal), "last-modified"); cal.setTime(now); _r.setHeaderForKey(WOMessage.httpFormatDate(cal), "date"); cal.add(Calendar.SECOND, this.expirationIntervalForMimeType(mimeType)); _r.setHeaderForKey(WOMessage.httpFormatDate(cal), "expires"); /* start streaming */ _r.enableStreaming(); byte[] buffer = new byte[0xFFFF]; for (int len; (len = is.read(buffer)) != -1;) _r.appendContentData(buffer, len); } catch (IOException e) { log.error("IO error trying to deliver resource: " + this.url, e); _r.setStatus(WOMessage.HTTP_STATUS_INTERNAL_ERROR); } finally { try { if (is != null) is.close(); } catch (IOException e) { log.warn("could not close URL input stream: " + this.url, e); } } } /* recursive lookup */ public Object lookupName(String _name, IJoContext _ctx, boolean _acquire) { /* only process names, don't try to be smart */ if ("/".equals(_name) || "..".equals(_name) || ".".equals(_name)) return null; URL nurl = null; try { // ugly hack String s = this.url.toExternalForm(); if (!s.endsWith("/")) s += "/"; nurl = new URL(s + _name); } catch (MalformedURLException e) { return e; } if (nurl == null) return null; return new JoResource(nurl); } /* description */ @Override public void appendAttributesToDescription(StringBuilder _d) { super.appendAttributesToDescription(_d); if (this.url != null) _d.append(" url=" + this.url); } }