Servlet pro zpřístupnění fotek, které se nacházejí ve zvláštním adresáři.
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/java/nekurak.net-web/src/java/cz/frantovo/nekurak/servlet/Fotky.java Sat Mar 13 23:11:01 2010 +0100
1.3 @@ -0,0 +1,118 @@
1.4 +package cz.frantovo.nekurak.servlet;
1.5 +
1.6 +import java.io.File;
1.7 +import java.io.FileInputStream;
1.8 +import java.io.IOException;
1.9 +import java.io.InputStream;
1.10 +import java.util.logging.Level;
1.11 +import java.util.logging.Logger;
1.12 +import java.util.regex.Pattern;
1.13 +import javax.servlet.ServletException;
1.14 +import javax.servlet.ServletOutputStream;
1.15 +import javax.servlet.http.HttpServlet;
1.16 +import javax.servlet.http.HttpServletRequest;
1.17 +import javax.servlet.http.HttpServletResponse;
1.18 +
1.19 +/**
1.20 + * Servlet pro zpřístupnění fotek, které se nacházejí ve zvláštním adresáři.
1.21 + *
1.22 + * Má jeden inicializační parametr:
1.23 + * adresar – cesta k adresáři na disku, kde se nacházejí fotky.
1.24 + * např. /var/www/nekurak.net/fotky
1.25 + *
1.26 + * Očekává se struktura adresářů tohoto typu:
1.27 + * Plné rozlišení: /var/www/nekurak.net/fotky/original/1.jpg
1.28 + * Náhled fotky: /var/www/nekurak.net/fotky/nahled/1.jpg
1.29 + * Lze ovlivnit konstantami níže
1.30 + * @author fiki
1.31 + */
1.32 +public class Fotky extends HttpServlet {
1.33 +
1.34 + /** Název inicializačního parametru */
1.35 + private static final String INIT_ADRESAR = "adresar";
1.36 + /** Název podadresáře obsahujícího fotku v plném rozlišení */
1.37 + private static final String PODADRESAR_ORIGINAL = "original";
1.38 + /** Název podadresáře obsahujícího výchozí náhled fotky */
1.39 + private static final String PODADRESAR_NAHLED = "nahled";
1.40 + private static final String PRIPONA = "jpg";
1.41 + private static final String LOMITKO = File.separator;
1.42 + /** Regulární výraz */
1.43 + private static final String VZOR_CESTY = "^" + LOMITKO + "(" + PODADRESAR_ORIGINAL + "|" + PODADRESAR_NAHLED + ")" + LOMITKO + "\\d+\\." + PRIPONA + "$";
1.44 + private static final String MIME_TYP = "image/jpeg";
1.45 + private File adresar;
1.46 + private static final Logger log = Logger.getLogger(Fotky.class.getSimpleName());
1.47 +
1.48 + @Override
1.49 + public void init() throws ServletException {
1.50 + super.init();
1.51 + String initAdresar = getServletConfig().getInitParameter(INIT_ADRESAR);
1.52 + adresar = new File(initAdresar);
1.53 + if (adresar.isDirectory()) {
1.54 + log.log(Level.INFO, "Servlet „Fotka“ byl úspěšně inicializován.");
1.55 + log.log(Level.INFO, "Adresář s fotkami: " + initAdresar);
1.56 + log.log(Level.INFO, "RegExp cesty: " + VZOR_CESTY);
1.57 + } else {
1.58 + throw new ServletException("Servlet „Fotka“ se nepodařilo inicializovat. Cesta: " + initAdresar);
1.59 + }
1.60 + }
1.61 +
1.62 + /**
1.63 + * @param pozadavek pouze GET (není důvod podporovat POST)
1.64 + * @param odpoved
1.65 + * @throws ServletException např. pokud parametr id není číslo
1.66 + * @throws IOException
1.67 + */
1.68 + @Override
1.69 + protected void doGet(HttpServletRequest pozadavek, HttpServletResponse odpoved) throws ServletException, IOException {
1.70 +
1.71 + String cesta = zkontrolujParametr(pozadavek.getPathInfo());
1.72 + File soubor = new File(adresar, cesta);
1.73 +
1.74 + if (soubor.isFile() && soubor.canRead()) {
1.75 +
1.76 + if (soubor.lastModified() > pozadavek.getDateHeader("If-Modified-Since")) {
1.77 + /** Soubor se změnil nebo ho klient ještě nemá načtený. */
1.78 + odpoved.setContentType(MIME_TYP);
1.79 + odpoved.setContentLength((int) soubor.length());
1.80 + odpoved.setDateHeader("Last-Modified", soubor.lastModified());
1.81 +
1.82 + ServletOutputStream out = odpoved.getOutputStream();
1.83 + InputStream in = new FileInputStream(soubor);
1.84 +
1.85 + try {
1.86 + byte[] bytes = new byte[1024];
1.87 + int bajtuNacteno;
1.88 + while ((bajtuNacteno = in.read(bytes)) != -1) {
1.89 + out.write(bytes, 0, bajtuNacteno);
1.90 + }
1.91 + } catch (Exception e) {
1.92 + throw new ServletException("Chyba při odesílání obrázku klientovi.", e);
1.93 + } finally {
1.94 + in.close();
1.95 + out.close();
1.96 + }
1.97 + } else {
1.98 + /** Soubor se od posledního načtení klientem nezměnil → není potřeba ho posílat znova. */
1.99 + odpoved.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
1.100 + }
1.101 +
1.102 + } else {
1.103 + /** Neexistující nebo nečitelný soubor → HTTP 404 chyba */
1.104 + odpoved.sendError(HttpServletResponse.SC_NOT_FOUND);
1.105 + }
1.106 + }
1.107 +
1.108 + /**
1.109 + * @param cesta cesta požadovaná klientem: request.getPathInfo();
1.110 + * @throws ServletException pokud cesta nevyhovuje vzoru
1.111 + */
1.112 + private static String zkontrolujParametr(String cesta) throws ServletException {
1.113 + if (Pattern.matches(VZOR_CESTY, cesta)) {
1.114 + /** cesta je v pořádku → pokračujeme */
1.115 + return cesta;
1.116 + } else {
1.117 + /** Chybná cesta → HTTP 500 chyba */
1.118 + throw new ServletException("Chybná cesta k obrázku: " + cesta);
1.119 + }
1.120 + }
1.121 +}
2.1 --- a/java/nekurak.net-web/web/WEB-INF/web.xml Thu Mar 11 11:55:52 2010 +0100
2.2 +++ b/java/nekurak.net-web/web/WEB-INF/web.xml Sat Mar 13 23:11:01 2010 +0100
2.3 @@ -1,61 +1,80 @@
2.4 <?xml version="1.0" encoding="UTF-8"?>
2.5 <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
2.6 <session-config>
2.7 - <session-timeout>30</session-timeout>
2.8 + <session-timeout>30</session-timeout>
2.9 </session-config>
2.10 -
2.11 <welcome-file-list>
2.12 - <welcome-file>index.jsp</welcome-file>
2.13 + <welcome-file>index.jsp</welcome-file>
2.14 </welcome-file-list>
2.15 -
2.16 + <!-- <chybovéStránky> -->
2.17 <error-page>
2.18 - <!-- Stránka nenalezena -->
2.19 - <error-code>404</error-code>
2.20 - <location>/WEB-INF/chyby/404.jsp</location>
2.21 + <!-- Stránka nenalezena -->
2.22 + <error-code>404</error-code>
2.23 + <location>/WEB-INF/chyby/404.jsp</location>
2.24 </error-page>
2.25 <error-page>
2.26 - <!-- Interní chyba serveru -->
2.27 - <error-code>500</error-code>
2.28 - <location>/WEB-INF/chyby/500.jsp</location>
2.29 + <!-- Interní chyba serveru -->
2.30 + <error-code>500</error-code>
2.31 + <location>/WEB-INF/chyby/500.jsp</location>
2.32 </error-page>
2.33 -
2.34 + <!-- </chybovéStránky> -->
2.35 + <!-- <definiceServletů> -->
2.36 <servlet>
2.37 - <servlet-name>atom</servlet-name>
2.38 - <jsp-file>/WEB-INF/atom/atom.jsp</jsp-file>
2.39 + <servlet-name>atom</servlet-name>
2.40 + <jsp-file>/WEB-INF/atom/atom.jsp</jsp-file>
2.41 </servlet>
2.42 -
2.43 + <servlet>
2.44 + <description>
2.45 + Servlet zpřístupňující fotky umístěné ve zvláštním adresáři
2.46 + (data oddělená od aplikace).
2.47 + </description>
2.48 + <servlet-name>fotky</servlet-name>
2.49 + <servlet-class>cz.frantovo.nekurak.servlet.Fotky</servlet-class>
2.50 + <init-param>
2.51 + <description>
2.52 + Adresář na disku, který obsahuje fotky podniků.
2.53 + Musí existovat při startu aplikace.
2.54 + </description>
2.55 + <param-name>adresar</param-name>
2.56 + <param-value>/var/www/nekurak.net/fotky</param-value>
2.57 + </init-param>
2.58 + </servlet>
2.59 + <!-- </definiceServletů> -->
2.60 + <!-- <mapováníServletů> -->
2.61 <servlet-mapping>
2.62 - <servlet-name>atom</servlet-name>
2.63 - <url-pattern>/atom/*</url-pattern>
2.64 + <servlet-name>fotky</servlet-name>
2.65 + <url-pattern>/fotky/*</url-pattern>
2.66 </servlet-mapping>
2.67 -
2.68 + <servlet-mapping>
2.69 + <servlet-name>atom</servlet-name>
2.70 + <url-pattern>/atom/*</url-pattern>
2.71 + </servlet-mapping>
2.72 + <!-- </mapováníServletů> -->
2.73 <context-param>
2.74 - <!-- Pro případ, že chybí hlavička „Accept-language“ v HTTP požadavku -->
2.75 - <param-name>javax.servlet.jsp.jstl.fmt.fallbackLocale</param-name>
2.76 - <param-value>cs</param-value>
2.77 + <!-- Pro případ, že chybí hlavička „Accept-language“ v HTTP požadavku -->
2.78 + <param-name>javax.servlet.jsp.jstl.fmt.fallbackLocale</param-name>
2.79 + <param-value>cs</param-value>
2.80 </context-param>
2.81 -
2.82 <!-- <zabezpečení> -->
2.83 <security-role>
2.84 - <role-name>opravneny</role-name>
2.85 + <role-name>opravneny</role-name>
2.86 </security-role>
2.87 <security-constraint>
2.88 - <web-resource-collection>
2.89 - <web-resource-name>Správa Nekuřák.net</web-resource-name>
2.90 - <url-pattern>/sprava/*</url-pattern>
2.91 - </web-resource-collection>
2.92 - <auth-constraint>
2.93 - <role-name>opravneny</role-name>
2.94 - </auth-constraint>
2.95 + <web-resource-collection>
2.96 + <web-resource-name>Správa Nekuřák.net</web-resource-name>
2.97 + <url-pattern>/sprava/*</url-pattern>
2.98 + </web-resource-collection>
2.99 + <auth-constraint>
2.100 + <role-name>opravneny</role-name>
2.101 + </auth-constraint>
2.102 </security-constraint>
2.103 <login-config>
2.104 - <auth-method>FORM</auth-method>
2.105 - <realm-name>nekurakNET</realm-name>
2.106 - <form-login-config>
2.107 - <form-login-page>/?akce=prihlaseni</form-login-page>
2.108 - <form-error-page>/?akce=prihlaseni&chyba=ano</form-error-page>
2.109 - </form-login-config>
2.110 + <auth-method>FORM</auth-method>
2.111 + <realm-name>nekurakNET</realm-name>
2.112 + <form-login-config>
2.113 + <form-login-page>/?akce=prihlaseni</form-login-page>
2.114 + <form-error-page>/?akce=prihlaseni&chyba=ano</form-error-page>
2.115 + </form-login-config>
2.116 </login-config>
2.117 <!-- </zabezpečení> -->
2.118 -
2.119 </web-app>