설치된 자바 버전과 프로젝트의 컴파일러 버전이 맞지 않을때 나는 에러입니다.
물론 실행은 잘 되고 있을 확률이 높음...

Error: Java compiler level does not match the version of the installed Java project facet

프로젝트에 마우스 오른쪽 > Properties > Project Facets
자바버전을 설치된 것과 같은 것으로 맞춰주면 해결됩니다.

 

I faced the same issue when I tried to deploy using the Ant tool.

The solution that worked for me was:

  • Right click on project, and then click Properties
  • Go to Java Build Path
  • Go to JRE System Library
  • Execution Environment was selected; I instead selected Alternate JRE and then jre7 (as shown below)

enter image description here

 

Maven Resource Filtering 사용 시에 An error occured while filtering resources 오류가 발생하는 경우가 있습니다.


이때, 프로젝트 메뉴에서 'Maven > Update Project...' 또는 Alt + F5 를 눌러서 업데이트를 수행하고 나면 에러가 사라집니다.

 

서론

Springframework에서 MySQL을 사용할 때 특정 시점이 지나면 자동으로 커넥션을 잃어버리는 문제가 있다. 이 문제는 Springframework에서 아무런 오랜시간 동안 데이터요청이 없으면 커넥션과 풀링을 해지하는 기능을 가지고 있기 때문인데 이 문제를 해결하기 위한 방법을 소개한다.

Srping에서 MySQL 커넥션 문제

이번 프로젝트에서 Springframework + Hiberante + MySQL을 사용하여 프로젝트 개발을 진행하는 도중에 스케줄러가 돌면서 특정 시점이 되어서 아래와 같은 JDBCConnectionException 을 자꾸만 발생하였다. apache의 common-dbcp를 사용해서 dataSource를 하다가 tomcat-jdbc로 교체하여 JNDI(Java Naming and Directory Interface) dataSource로 사용하면서 발생했다. JNDI 방법을 사용하는 것은 이번이 처음이였기 때문에 더구나 지금까지 대부분 Oracle을 사용하다가 Spring framework + MySQL을 처음 다루기에 전에 보지 못한 예외들이 발생하는거라 생각했다. 여러가지 자료를 찾아보다 이 문제는 MySQL이 기본적으로 8시간동안 요청이 없으면 커넥션을 해지하고 풀링을 해지 하기 때문이라는 것을 알게 되었다. 프로젝트에서는 Spring framework의 @Scheduled를 이용해서 Tomcat 서버에서 스케줄을하는데 웹 요청이 들어오지 않고 JNDI를 이용해서 스케줄에서 Hibernate와 MySQL을 사용해서 생기는 문제로 여겨졌다.

org.springframework.dao.DataAccessResourceFailureException: could not execute query; nested exception is org.hibernate.exception.JDBCConnectionException: could not execute query
        at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:629)
        at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
        at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
        at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
        at org.springframework.orm.hibernate3.HibernateTemplate.find(HibernateTemplate.java:912)
        at org.springframework.orm.hibernate3.HibernateTemplate.find(HibernateTemplate.java:904)
        at net.hibrain.apps.push.model.PushProviderDaoImpl.findWillPushDevices(PushProviderDaoImpl.java:50)
        at net.hibrain.apps.push.model.PushProviderDaoImpl.insertAllPushDeviceJSON(PushProviderDaoImpl.java:131)
        at net.hibrain.apps.push.service.PushProviderServiceImpl.start(PushProviderServiceImpl.java:111)
        at net.hibrain.apps.push.service.PushProviderServiceImpl.start(PushProviderServiceImpl.java:61)
        at net.hibrain.apps.push.schedule.PushScheduleServiceImpl.startSyncronous(PushScheduleServiceImpl.java:34)
        at sun.reflect.GeneratedMethodAccessor47.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:64)
        at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:53)
        at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
        at java.util.concurrent.FutureTask.run(FutureTask.java:138)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:206)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:662)
Caused by: org.hibernate.exception.JDBCConnectionException: could not execute query
        at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:97)
        at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
        at org.hibernate.loader.Loader.doList(Loader.java:2231)
        at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2125)
        at org.hibernate.loader.Loader.list(Loader.java:2120)
        at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:401)
        at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:361)
        at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
        at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1148)
        at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
        at org.springframework.orm.hibernate3.HibernateTemplate$30.doInHibernate(HibernateTemplate.java:921)
        at org.springframework.orm.hibernate3.HibernateTemplate$30.doInHibernate(HibernateTemplate.java:1)
        at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
        ... 22 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure


The last packet successfully received from the server was 35,986,917 milliseconds ago.  The last packet sent successfully to the server was 22 milliseconds ago.
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
        at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1116)
        at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3102)
        at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2991)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3532)
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2002)
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2163)
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2624)
        at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2127)
        at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2293)
        at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
        at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
        at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
        at org.hibernate.loader.Loader.getResultSet(Loader.java:1808)
        at org.hibernate.loader.Loader.doQuery(Loader.java:697)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
        at org.hibernate.loader.Loader.doList(Loader.java:2228)
        ... 32 more

MySQL에서 wait_time 조회하기

show global variables like 'wait%';

MySQL은 기본적으로 8시간동안 요청이 없으면 커넥션을 해지한다. 방법은 리소스를 설정하는 MySQL url에다가 autoReconnection=true로 변경하면 된다. 또는 valdationQuery="select 1"`을 전처리로 실행하게하면 된다.


<Resource name="jdbc/test_database" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000" validationQuery="select 1"
username="ID" password="PASSWORD" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost: 3306/test_database?autoReconnection=true"/>

또는 스프링 프레임워크에서 hibernateProperties를 설정하는 곳에서 설정하면 된다. 다음은 그 설정 예이다. 이 설정 방법은 다음 블로그에서 참조했다. (http://mimul.com/pebble/default/2008/06/24/1214258760000.html)

<bean id="hibernateProperties"
          class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="properties">
            <props>
                <prop key="hibernate3.hbm2ddl.auto">update</prop>
                <prop key="hibernate3.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate3.c3p0.minPoolSize">15</prop>
                <prop key="hibernate3.c3p0.maxPoolSize">50</prop>
                <prop key="hibernate3.c3p0.timeout">600</prop>
                <prop key="hibernate3.c3p0.max_statement">50</prop>
                <prop key="hibernate3.c3p0.testConnectionOnCheckin">true</prop>
                <prop key="hibernate3.c3p0.testConnectionOnCheckout">false</prop>
                <prop key="hibernate3.c3p0.maxStatementsPerConnection">5</prop>
                <prop key="hibernate3.c3p0.maxIdleTime">300</prop>
                <prop key="hibernate3.c3p0.maxConnectionAge">14400</prop>
                <prop key="hibernate3.c3p0.acquireRetryAttempts">10</prop>
                <prop key="hibernate3.c3p0.preferredTestQuery">SELECT 1;</prop>
                <prop key="hibernate3.c3p0.idleConnectionTestPeriod">300</prop>
                <prop key="hibernate3.provider">org.hibernate.connection.C3P0ConnectionProvider</prop>
            </props>
        </property>
    </bean>

이 방법 외에도 /etc/my.cnf에서도 설정하는 방법도 있고 유지하는 방법 여러가지 있으니 프로젝트에 맞는 방법을 선택하여 사용하면 될것 같다.

 

이클립스에서 STS를 설치하고, Spring 프로젝트를 생성하고나서 


src/main/resources 폴더에 새로운 폴더를 추가하면, 당연히 폴더 아이콘으로 보여야하는데, 패키지로 보이는 


경우가 있습니다. 




아니! 나는 폴더를 생성했는데, 시방 무슨 패키지가 생성되었어?!?! 라고 생각하시면서, 내가 잘못했나?

다시 해볼까? 하시면서 몇번을 만들어도 똑같을 겁니다.


사실 이건 정상적인 상황으로 실제 프로젝트에는 문제가 없지만, 좀 찜찜하고 눈에 거슬리기도 합니다.

이럴때는 다음과 같이 설정하시면 됩니다.


1. 프로젝트 우클릭 -> Properties


2. Java Build Path -> Source 선택


3. 하단에 있는 /src/main/resources의 Excluded를 선택하고 Edit



4. Exclusion patterns의 Add를 선택하고 ** 를 입력


5. Finish

그럼 다음과 같이 폴더 형식으로 보입니다.


해결 완료!

public static String getClientIpAddr(HttpServletRequest request) {

String ip = request.getHeader("X-Forwarded-For");

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = request.getHeader("Proxy-Client-IP");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = request.getHeader("WL-Proxy-Client-IP");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = request.getHeader("HTTP_CLIENT_IP");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = request.getHeader("HTTP_X_FORWARDED_FOR");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = request.getRemoteAddr();

}

return ip;

}

 

물론 아래 소스를 복사하여 붙여넣은뒤, 자신의 시스템에 맞게 커스텀마이징 해주셔야 합니다...




/**
* net/balusc/webapp/FileServlet.java
*
* Copyright (C) 2009 BalusC
*
* This program 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 3
* of the License, or (at your option) any later version.
*
* This library 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 this library.
* If not, see .
*/

import org.springframework.web.servlet.view.AbstractView;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
* LGPL code from http://balusc.blogspot.in/2009/02/fileservlet-supporting-resume-and.html adopted
* as Spring View for streaming binary files.
*
* @author Atul M Dambalkar (Adapted for Spring View)
*/
public class StreamingViewRenderer extends AbstractView {

    // Constants ----------------------------------------------------------------------------------

    private static final int DEFAULT_BUFFER_SIZE = 20480; // ..bytes = 20KB.
    private static final long DEFAULT_EXPIRE_TIME = 604800000L; // ..ms = 1 week.
    private static final String MULTIPART_BOUNDARY = "MULTIPART_BYTERANGES";

    @Override
    protected void renderMergedOutputModel(Map objectMap,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {

        InputStream dataStream =  (InputStream) objectMap.get(DownloadConstants.INPUT_STREAM);
       
        if (dataStream == null) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        long length = (Long) objectMap.get(DownloadConstants.CONTENT_LENGTH);
        String fileName = (String) objectMap.get(DownloadConstants.FILENAME);
        Date lastModifiedObj = (Date)objectMap.get(DownloadConstants.LAST_MODIFIED);

        if (StringUtils.isEmpty(fileName) || lastModifiedObj == null) {
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            return;
        }
        long lastModified = lastModifiedObj.getTime();
        String contentType = (String) objectMap.get(DownloadConstants.CONTENT_TYPE);

        // Validate request headers for caching ---------------------------------------------------

        // If-None-Match header should contain "*" or ETag. If so, then return 304.
        String ifNoneMatch = request.getHeader("If-None-Match");
        if (ifNoneMatch != null && HttpUtils.matches(ifNoneMatch, fileName)) {
            response.setHeader("ETag", fileName); // Required in 304.
            response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
            return;
        }

        // If-Modified-Since header should be greater than LastModified. If so, then return 304.
        // This header is ignored if any If-None-Match header is specified.
        long ifModifiedSince = request.getDateHeader("If-Modified-Since");
        if (ifNoneMatch == null && ifModifiedSince != -1 && ifModifiedSince + 1000 > lastModified) {
            response.setHeader("ETag", fileName); // Required in 304.
            response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
            return;
        }

        // Validate request headers for resume ----------------------------------------------------

        // If-Match header should contain "*" or ETag. If not, then return 412.
        String ifMatch = request.getHeader("If-Match");
        if (ifMatch != null && !HttpUtils.matches(ifMatch, fileName)) {
            response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
            return;
        }

        // If-Unmodified-Since header should be greater than LastModified. If not, then return 412.
        long ifUnmodifiedSince = request.getDateHeader("If-Unmodified-Since");
        if (ifUnmodifiedSince != -1 && ifUnmodifiedSince + 1000 <= lastModified) {
            response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
            return;
        }
       
        // Validate and process range -------------------------------------------------------------

        // Prepare some variables. The full Range represents the complete file.
        Range full = new Range(0, length - 1, length);
        List ranges = new ArrayList();

        // Validate and process Range and If-Range headers.
        String range = request.getHeader("Range");
        if (range != null) {

            // Range header should match format "bytes=n-n,n-n,n-n...". If not, then return 416.
            if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) {
                response.setHeader("Content-Range", "bytes */" + length); // Required in 416.
                response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                return;
            }

            String ifRange = request.getHeader("If-Range");
            if (ifRange != null && !ifRange.equals(fileName)) {
                try {
                    long ifRangeTime = request.getDateHeader("If-Range"); // Throws IAE if invalid.
                    if (ifRangeTime != -1) {
                        ranges.add(full);
                    }
                } catch (IllegalArgumentException ignore) {
                    ranges.add(full);
                }
            }

            // If any valid If-Range header, then process each part of byte range.
            if (ranges.isEmpty()) {
                for (String part : range.substring(6).split(",")) {
                    // Assuming a file with length of 100, the following examples returns bytes at:
                    // 50-80 (50 to 80), 40- (40 to length=100), -20 (length-20=80 to length=100).
                    long start = StringUtils.sublong(part, 0, part.indexOf("-"));
                    long end = StringUtils.sublong(part, part.indexOf("-") + 1, part.length());

                    if (start == -1) {
                        start = length - end;
                        end = length - 1;
                    } else if (end == -1 || end > length - 1) {
                        end = length - 1;
                    }

                    // Check if Range is syntactically valid. If not, then return 416.
                    if (start > end) {
                        response.setHeader("Content-Range", "bytes */" + length); // Required in 416.
                        response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                        return;
                    }

                    // Add range.                   
                    ranges.add(new Range(start, end, length));
                }
            }
        }

        // Prepare and initialize response --------------------------------------------------------

        // Get content type by file name and set content disposition.
        String disposition = "inline";

        // If content type is unknown, then set the default value.
        // For all content types, see: http://www.w3schools.com/media/media_mimeref.asp
        // To add new content types, add new mime-mapping entry in web.xml.
        if (contentType == null) {
            contentType = "application/octet-stream";
        } else if (!contentType.startsWith("image")) {
            // Else, expect for images, determine content disposition. If content type is supported by
            // the browser, then set to inline, else attachment which will pop a 'save as' dialogue.
            String accept = request.getHeader("Accept");
            disposition = accept != null && HttpUtils.accepts(accept, contentType)
                                    ? "inline" : "attachment";
        }

        // Initialize response.
        response.reset();
        response.setBufferSize(DEFAULT_BUFFER_SIZE);
        response.setHeader("Content-Disposition", disposition + ";filename=\"" + fileName + "\"");
        response.setHeader("Accept-Ranges", "bytes");
        response.setHeader("ETag", fileName);
        response.setDateHeader("Last-Modified", lastModified);
        response.setDateHeader("Expires", System.currentTimeMillis() + DEFAULT_EXPIRE_TIME);

        // Send requested file (part(s)) to client ------------------------------------------------

        // Prepare streams.
        InputStream input = null;
        OutputStream output = null;

        try {
            // Open streams.
            input = new BufferedInputStream(dataStream);
            output = response.getOutputStream();

            if (ranges.isEmpty() || ranges.get(0) == full) {

                // Return full file.
                Range r = full;
                response.setContentType(contentType);
                response.setHeader("Content-Range", "bytes " + r.start + "-" + r.end + "/" + r.total);
                response.setHeader("Content-Length", String.valueOf(r.length));
                copy(input, output, length, r.start, r.length);
               
            } else if (ranges.size() == 1) {

                // Return single part of file.
                Range r = ranges.get(0);
                response.setContentType(contentType);
                response.setHeader("Content-Range", "bytes " + r.start + "-" + r.end + "/" + r.total);
                response.setHeader("Content-Length", String.valueOf(r.length));
                response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); // 206.

                // Copy single part range.
                copy(input, output, length, r.start, r.length);

            } else {

                // Return multiple parts of file.
                response.setContentType("multipart/byteranges; boundary=" + MULTIPART_BOUNDARY);
                response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); // 206.

                // Cast back to ServletOutputStream to get the easy println methods.
                ServletOutputStream sos = (ServletOutputStream) output;

                // Copy multi part range.
                for (Range r : ranges) {
                    // Add multipart boundary and header fields for every range.
                    sos.println();
                    sos.println("--" + MULTIPART_BOUNDARY);
                    sos.println("Content-Type: " + contentType);
                    sos.println("Content-Range: bytes " + r.start + "-" + r.end + "/" + r.total);

                    // Copy single part range of multi part range.
                    copy(input, output, length, r.start, r.length);
                }

                // End with multipart boundary.
                sos.println();
                sos.println("--" + MULTIPART_BOUNDARY + "--");
            }
        } finally {
            // Gently close streams.
            close(output);
            close(input);
            close(dataStream);
        }

    }

    /**
     * Close the given resource.
     * @param resource The resource to be closed.
     */
    private static void close(Closeable resource) {
        if (resource != null) {
            try {
                resource.close();
            } catch (IOException ignore) {
                // Ignore IOException. If you want to handle this anyway, it might be useful to know
                // that this will generally only be thrown when the client aborted the request.
            }
        }
    }
   
    /**
     * Copy the given byte range of the given input to the given output.
     * @param input The input to copy the given range to the given output for.
     * @param output The output to copy the given range from the given input for.
     * @param start Start of the byte range.
     * @param length Length of the byte range.
     * @throws IOException If something fails at I/O level.
     */
    private static void copy(InputStream input, OutputStream output,
                             long inputSize, long start, long length)
        throws IOException
    {
        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
        int read;

        if (inputSize == length) {
            // Write full range.
            while ((read = input.read(buffer)) > 0) {
                output.write(buffer, 0, read);
                output.flush();
            }
        } else {
            input.skip(start);
            long toRead = length;

            while ((read = input.read(buffer)) > 0) {
                if ((toRead -= read) > 0) {
                    output.write(buffer, 0, read);
                    output.flush();
                } else {
                    output.write(buffer, 0, (int) toRead + read);
                    output.flush();
                    break;
                }
            }
        }
    }

    // Inner classes ------------------------------------------------------------------------------

    /**
     * This class represents a byte range.
     */
    protected class Range {
        long start;
        long end;
        long length;
        long total;

        /**
         * Construct a byte range.
         * @param start Start of the byte range.
         * @param end End of the byte range.
         * @param total Total length of the byte source.
         */
        public Range(long start, long end, long total) {
            this.start = start;
            this.end = end;
            this.length = end - start + 1;
            this.total = total;
        }
    }
}

public class DownloadConstants {

public static final String INPUT_STREAM = "inputStream";
public static final String CONTENT_TYPE = "contentType";

public static final String CONTENT_LENGTH = "contentLength";
public static final String FILENAME = "filename";
    public static final String LAST_MODIFIED = "lastModified";
}

public class HttpUtils {
   
    /**
     * Returns true if the given accept header accepts the given value.
     * @param acceptHeader The accept header.
     * @param toAccept The value to be accepted.
     * @return True if the given accept header accepts the given value.
     */
    public static boolean accepts(String acceptHeader, String toAccept) {
        String[] acceptValues = acceptHeader.split("\\s*(,|;)\\s*");
        Arrays.sort(acceptValues);
        return Arrays.binarySearch(acceptValues, toAccept) > -1
            || Arrays.binarySearch(acceptValues, toAccept.replaceAll("/.*$", "/*")) > -1
            || Arrays.binarySearch(acceptValues, "*/*") > -1;
    }

    /**
     * Returns true if the given match header matches the given value.
     * @param matchHeader The match header.
     * @param toMatch The value to be matched.
     * @return True if the given match header matches the given value.
     */
    public static boolean matches(String matchHeader, String toMatch) {
        String[] matchValues = matchHeader.split("\\s*,\\s*");
        Arrays.sort(matchValues);
        return Arrays.binarySearch(matchValues, toMatch) > -1
            || Arrays.binarySearch(matchValues, "*") > -1;
    }
}

public class StringUtils {

    /**
     * Returns a substring of the given string value from the given begin index to the given end
     * index as a long. If the substring is empty, then -1 will be returned
     * @param value The string value to return a substring as long for.
     * @param beginIndex The begin index of the substring to be returned as long.
     * @param endIndex The end index of the substring to be returned as long.
     * @return A substring of the given string value as long or -1 if substring is empty.
     */
    public static long sublong(String value, int beginIndex, int endIndex) {
        String substring = value.substring(beginIndex, endIndex);
        return (substring.length() > 0) ? Long.parseLong(substring) : -1;
    }   
   
}

<fmt:formatNumber value="${docExtra.docScore}" type="pattern" pattern="0.0"/>

+ Recent posts