Java tutorial
/** * personium.io * Copyright 2014 FUJITSU LIMITED * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.fujitsu.dc.core.rs.cell; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.util.Date; import java.util.List; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.StreamingOutput; import javax.ws.rs.core.UriInfo; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.apache.commons.io.IOUtils; import org.apache.http.HttpStatus; import org.apache.wink.webdav.WebDAVMethod.PROPFIND; import org.apache.wink.webdav.model.Creationdate; import org.apache.wink.webdav.model.Getcontentlength; import org.apache.wink.webdav.model.Getcontenttype; import org.apache.wink.webdav.model.Getlastmodified; import org.apache.wink.webdav.model.Multistatus; import org.apache.wink.webdav.model.ObjectFactory; import org.apache.wink.webdav.model.Propfind; import org.apache.wink.webdav.model.Resourcetype; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fujitsu.dc.common.utils.DcCoreUtils; import com.fujitsu.dc.core.DcCoreException; import com.fujitsu.dc.core.auth.AccessContext; import com.fujitsu.dc.core.auth.CellPrivilege; import com.fujitsu.dc.core.event.EventUtils; import com.fujitsu.dc.core.eventlog.ArchiveLogCollection; import com.fujitsu.dc.core.eventlog.ArchiveLogFile; import com.fujitsu.dc.core.model.Cell; import com.fujitsu.dc.core.model.DavRsCmp; import com.fujitsu.dc.core.utils.ResourceUtils; /** * JAX-RS Resource. */ public class LogResource { /** archive??. */ public static final String ARCHIVE_COLLECTION = "archive"; /** current??. */ public static final String CURRENT_COLLECTION = "current"; private static final String DEFAULT_LOG = "default.log"; Cell cell; AccessContext accessContext; DavRsCmp davRsCmp; static Logger log = LoggerFactory.getLogger(LogResource.class); /** * . * @param cell Cell * @param accessContext AccessContext * @param davRsCmp DavRsCmp */ public LogResource(final Cell cell, final AccessContext accessContext, final DavRsCmp davRsCmp) { this.accessContext = accessContext; this.cell = cell; this.davRsCmp = davRsCmp; } /** * ????. * @return JAX-RS Response Object */ @Path(CURRENT_COLLECTION) @PROPFIND public final Response currentPropfind() { // ?????????501?? throw DcCoreException.Misc.METHOD_NOT_IMPLEMENTED; } /** * ????. * @param requestBodyXml Request Body * @param uriInfo URL * @param contentLength contentlength? * @param transferEncoding Transfer-Encoding? * @param depth Depth? * @return JAX-RS Response Object */ @Path(ARCHIVE_COLLECTION) @PROPFIND public final Response archivePropfind(final Reader requestBodyXml, @Context UriInfo uriInfo, @HeaderParam(HttpHeaders.CONTENT_LENGTH) final Long contentLength, @HeaderParam("Transfer-Encoding") final String transferEncoding, @HeaderParam(DcCoreUtils.HttpHeaders.DEPTH) final String depth) { // this.davRsCmp.checkAccessContext(this.davRsCmp.getAccessContext(), CellPrivilege.LOG_READ); // Depth??? 0, 1 // infinity?????????403?? if ("infinity".equals(depth)) { throw DcCoreException.Dav.PROPFIND_FINITE_DEPTH; } else if (depth == null) { throw DcCoreException.Dav.INVALID_DEPTH_HEADER.params("null"); } else if (!("0".equals(depth) || "1".equals(depth))) { throw DcCoreException.Dav.INVALID_DEPTH_HEADER.params(depth); } // ?? pf?? // ????allprop????????? Propfind propfind = null; if (ResourceUtils.hasApparentlyRequestBody(contentLength, transferEncoding)) { BufferedReader br = null; try { br = new BufferedReader(requestBodyXml); propfind = Propfind.unmarshal(br); } catch (Exception e) { throw DcCoreException.Dav.XML_ERROR.reason(e); } } if (null != propfind && !propfind.isAllprop()) { throw DcCoreException.Dav.XML_CONTENT_ERROR; } // archive?????? ArchiveLogCollection archiveLogCollection = new ArchiveLogCollection(this.cell, uriInfo); archiveLogCollection.createFileInformation(); // ?? final Multistatus multiStatus = createMultiStatus(depth, archiveLogCollection); StreamingOutput str = new StreamingOutput() { @Override public void write(final OutputStream os) throws IOException, WebApplicationException { Multistatus.marshal(multiStatus, os); } }; return Response.status(HttpStatus.SC_MULTI_STATUS).entity(str) .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML).build(); } private Multistatus createMultiStatus(final String depth, ArchiveLogCollection archiveLogCollection) { ObjectFactory of = new ObjectFactory(); final Multistatus multiStatus = of.createMultistatus(); List<org.apache.wink.webdav.model.Response> responseList = multiStatus.getResponse(); // Archive???? org.apache.wink.webdav.model.Response collectionResponse = this.createPropfindResponse( archiveLogCollection.getCreated(), archiveLogCollection.getUpdated(), archiveLogCollection.getUrl(), null); responseList.add(collectionResponse); // Depth?1???????? if ("1".equals(depth)) { for (ArchiveLogFile archiveFile : archiveLogCollection.getArchivefileList()) { org.apache.wink.webdav.model.Response fileResponse = this.createPropfindResponse( archiveFile.getCreated(), archiveFile.getUpdated(), archiveFile.getUrl(), archiveFile.getSize()); responseList.add(fileResponse); } } return multiStatus; } /** * PROPFIND????. */ org.apache.wink.webdav.model.Response createPropfindResponse(long created, long updated, String href, Long size) { // href ObjectFactory of = new ObjectFactory(); org.apache.wink.webdav.model.Response ret = of.createResponse(); ret.getHref().add(href); // creationdate Creationdate cd = of.createCreationdate(); cd.setValue(new Date(created)); ret.setPropertyOk(cd); // getlastmodified Getlastmodified lm = of.createGetlastmodified(); lm.setValue(new Date(updated)); ret.setPropertyOk(lm); if (size != null) { // ?? // getcontentlength Getcontentlength contentLength = of.createGetcontentlength(); contentLength.setValue(String.valueOf(size)); ret.setPropertyOk(contentLength); // getcontenttype?"text/csv"? Getcontenttype contentType = of.createGetcontenttype(); contentType.setValue(EventUtils.TEXT_CSV); ret.setPropertyOk(contentType); // ?resourcetype Resourcetype colRt = of.createResourcetype(); ret.setPropertyOk(colRt); } else { // ?? // resourcetype?WebDav? Resourcetype colRt = of.createResourcetype(); colRt.setCollection(of.createCollection()); ret.setPropertyOk(colRt); } return ret; } /** * ??. * @param ifNoneMatch If-None-Match * @param logCollection Collection?? * @param fileName fileName * @return JAXRS Response */ @Path("{logCollection}/{filename}") @GET public final Response getLogFile(@HeaderParam(HttpHeaders.IF_NONE_MATCH) final String ifNoneMatch, @PathParam("logCollection") final String logCollection, @PathParam("filename") final String fileName) { // this.davRsCmp.checkAccessContext(this.davRsCmp.getAccessContext(), CellPrivilege.LOG_READ); // ?Collection???? if (!isValidLogCollection(logCollection)) { throw DcCoreException.Dav.RESOURCE_NOT_FOUND; } // ???default.log???404? if (!isValidLogFile(logCollection, fileName)) { throw DcCoreException.Dav.RESOURCE_NOT_FOUND; } String cellId = davRsCmp.getCell().getId(); String owner = davRsCmp.getCell().getOwner(); // ?? StringBuilder logFileName = EventUtils.getEventLogDir(cellId, owner); logFileName.append(logCollection); logFileName.append(File.separator); logFileName.append(fileName); return getLog(logCollection, logFileName.toString()); } private Response getLog(final String logCollection, String logFileName) { if (CURRENT_COLLECTION.equals(logCollection)) { File logFile = new File(logFileName); if (!logFile.isFile() || !logFile.canRead()) { // ????????????????SC_OK? return getEmptyResponse(); } try { final InputStream isInvariable = new FileInputStream(logFile); return createResponse(isInvariable); } catch (FileNotFoundException e) { throw DcCoreException.Dav.RESOURCE_NOT_FOUND; } } else { ZipArchiveInputStream zipArchiveInputStream = null; BufferedInputStream bis = null; String archiveLogFileName = logFileName + ".zip"; try { log.info("EventLog file path : " + archiveLogFileName); zipArchiveInputStream = new ZipArchiveInputStream(new FileInputStream(archiveLogFileName)); bis = new BufferedInputStream(zipArchiveInputStream); // ?entry?? // ??1??????????????? ZipArchiveEntry nextZipEntry = zipArchiveInputStream.getNextZipEntry(); if (nextZipEntry == null) { IOUtils.closeQuietly(bis); throw DcCoreException.Event.ARCHIVE_FILE_CANNOT_OPEN; } return createResponse(bis); } catch (FileNotFoundException e1) { // ??????404? throw DcCoreException.Dav.RESOURCE_NOT_FOUND; } catch (IOException e) { log.info("Failed to read archive entry : " + e.getMessage()); throw DcCoreException.Event.ARCHIVE_FILE_CANNOT_OPEN; } } } private Response createResponse(final InputStream isInvariable) { // ResponseBuilder res = Response.status(HttpStatus.SC_OK); res.header(HttpHeaders.CONTENT_TYPE, EventUtils.TEXT_CSV); res.entity(isInvariable); return res.build(); } /** * ???????????. * @return ? */ private Response getEmptyResponse() { // ??? ResponseBuilder res = Response.status(HttpStatus.SC_OK); res.header(HttpHeaders.CONTENT_TYPE, EventUtils.TEXT_CSV); res.entity(""); log.debug("main thread end."); return res.build(); } /** * . * @return ? */ @Path("{logCollection}/{filename}") @DELETE public final Response deleteLogFile() { throw DcCoreException.Misc.METHOD_NOT_IMPLEMENTED; } /** * ?Collection???. * @param collectionName Collection?? ( "current" or "archive" ) * @return true: ???false: */ protected boolean isValidLogCollection(String collectionName) { return CURRENT_COLLECTION.equals(collectionName) || ARCHIVE_COLLECTION.equals(collectionName); } /** * ????. * <ul> * <li>current: "default.log" * <li>archive: "default.log." ?????????404????????????) * </ul> * @param collectionName Collection?? ( "current" or "archive" ) * @param fileName ?? ( "default.log" or "default.log.*" ) * @return true: ???false: */ protected boolean isValidLogFile(String collectionName, String fileName) { if (CURRENT_COLLECTION.equals(collectionName)) { return DEFAULT_LOG.equals(fileName); } else { // ????? return fileName != null && fileName.startsWith(DEFAULT_LOG + "."); } } }