Refactor FileTypeRegsitery to be an interface

With only one concrete implementation, MimeUtilFileTypeRegistry,
which uses the MimeUtil library to make its decisions.

Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce
2009-07-28 08:04:42 -07:00
parent 2b8e2dbe42
commit 6791b2859f
3 changed files with 133 additions and 108 deletions

View File

@@ -14,63 +14,10 @@
package com.google.gerrit.server;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import eu.medsea.mimeutil.MimeException;
import eu.medsea.mimeutil.MimeType;
import eu.medsea.mimeutil.MimeUtil2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spearce.jgit.lib.RepositoryConfig;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Singleton
public class FileTypeRegistry {
private static final String KEY_SAFE = "safe";
private static final String SECTION_MIMETYPE = "mimetype";
private static final Logger log =
LoggerFactory.getLogger(FileTypeRegistry.class);
private final GerritServer server;
private MimeUtil2 mimeUtil;
@Inject
FileTypeRegistry(final GerritServer gs) {
server = gs;
mimeUtil = new MimeUtil2();
register("eu.medsea.mimeutil.detector.ExtensionMimeDetector");
register("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
if (isWin32()) {
register("eu.medsea.mimeutil.detector.WindowsRegistryMimeDetector");
}
}
private void register(String name) {
mimeUtil.registerMimeDetector(name);
}
private static boolean isWin32() {
final String osDotName =
AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty("os.name");
}
});
return osDotName != null
&& osDotName.toLowerCase().indexOf("windows") != -1;
}
public interface FileTypeRegistry {
/**
* Get the most specific MIME type available for a file.
*
@@ -84,34 +31,7 @@ public class FileTypeRegistry {
* or cannot be determined, {@link MimeUtil2#UNKNOWN_MIME_TYPE} which
* is an alias for {@code application/octet-stream}.
*/
public MimeType getMimeType(final String path, final byte[] content) {
Set<MimeType> mimeTypes = new HashSet<MimeType>();
if (content != null && content.length > 0) {
try {
mimeTypes.addAll(mimeUtil.getMimeTypes(content));
} catch (MimeException e) {
log.warn("Unable to determine MIME type from content", e);
}
}
try {
mimeTypes.addAll(mimeUtil.getMimeTypes(path));
} catch (MimeException e) {
log.warn("Unable to determine MIME type from path", e);
}
if (isUnknownType(mimeTypes)) {
return MimeUtil2.UNKNOWN_MIME_TYPE;
}
final List<MimeType> types = new ArrayList<MimeType>(mimeTypes);
Collections.sort(types, new Comparator<MimeType>() {
@Override
public int compare(MimeType a, MimeType b) {
return b.getSpecificity() - a.getSpecificity();
}
});
return types.get(0);
}
public abstract MimeType getMimeType(final String path, final byte[] content);
/**
* Is this content type safe to transmit to a browser directly?
@@ -122,30 +42,6 @@ public class FileTypeRegistry {
* content type and wants it to be protected (typically by wrapping
* the data in a ZIP archive).
*/
public boolean isSafeInline(final MimeType type) {
if (MimeUtil2.UNKNOWN_MIME_TYPE.equals(type)) {
// Most browsers perform content type sniffing when they get told
// a generic content type. This is bad, so assume we cannot send
// the file inline.
//
return false;
}
public abstract boolean isSafeInline(final MimeType type);
final RepositoryConfig cfg = server.getGerritConfig();
final boolean any = isSafe(cfg, "*/*", false);
final boolean genericMedia = isSafe(cfg, type.getMediaType() + "/*", any);
return isSafe(cfg, type.toString(), genericMedia);
}
private static boolean isSafe(RepositoryConfig cfg, String type, boolean def) {
return cfg.getBoolean(SECTION_MIMETYPE, type, KEY_SAFE, def);
}
private static boolean isUnknownType(Collection<MimeType> mimeTypes) {
if (mimeTypes.isEmpty()) {
return true;
}
return mimeTypes.size() == 1
&& mimeTypes.contains(MimeUtil2.UNKNOWN_MIME_TYPE);
}
}

View File

@@ -131,7 +131,7 @@ public class GerritServletConfig extends GuiceServletContextListener {
final GerritServer gs = GerritServer.getInstance(true);
bind(GerritServer.class).toInstance(gs);
bind(ContactStore.class).toInstance(EncryptedContactStore.create(gs));
bind(FileTypeRegistry.class).toInstance(new FileTypeRegistry(gs));
bind(FileTypeRegistry.class).to(MimeUtilFileTypeRegistry.class);
} catch (OrmException e) {
addError(e);
} catch (XsrfException e) {

View File

@@ -0,0 +1,129 @@
// Copyright (C) 2009 The Android Open Source Project
//
// 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.google.gerrit.server;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import eu.medsea.mimeutil.MimeException;
import eu.medsea.mimeutil.MimeType;
import eu.medsea.mimeutil.MimeUtil2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spearce.jgit.lib.RepositoryConfig;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Singleton
class MimeUtilFileTypeRegistry implements FileTypeRegistry {
private static final String KEY_SAFE = "safe";
private static final String SECTION_MIMETYPE = "mimetype";
private static final Logger log =
LoggerFactory.getLogger(MimeUtilFileTypeRegistry.class);
private final GerritServer server;
private MimeUtil2 mimeUtil;
@Inject
MimeUtilFileTypeRegistry(final GerritServer gs) {
server = gs;
mimeUtil = new MimeUtil2();
register("eu.medsea.mimeutil.detector.ExtensionMimeDetector");
register("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
if (isWin32()) {
register("eu.medsea.mimeutil.detector.WindowsRegistryMimeDetector");
}
}
private void register(String name) {
mimeUtil.registerMimeDetector(name);
}
private static boolean isWin32() {
final String osDotName =
AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty("os.name");
}
});
return osDotName != null
&& osDotName.toLowerCase().indexOf("windows") != -1;
}
public MimeType getMimeType(final String path, final byte[] content) {
Set<MimeType> mimeTypes = new HashSet<MimeType>();
if (content != null && content.length > 0) {
try {
mimeTypes.addAll(mimeUtil.getMimeTypes(content));
} catch (MimeException e) {
log.warn("Unable to determine MIME type from content", e);
}
}
try {
mimeTypes.addAll(mimeUtil.getMimeTypes(path));
} catch (MimeException e) {
log.warn("Unable to determine MIME type from path", e);
}
if (isUnknownType(mimeTypes)) {
return MimeUtil2.UNKNOWN_MIME_TYPE;
}
final List<MimeType> types = new ArrayList<MimeType>(mimeTypes);
Collections.sort(types, new Comparator<MimeType>() {
@Override
public int compare(MimeType a, MimeType b) {
return b.getSpecificity() - a.getSpecificity();
}
});
return types.get(0);
}
public boolean isSafeInline(final MimeType type) {
if (MimeUtil2.UNKNOWN_MIME_TYPE.equals(type)) {
// Most browsers perform content type sniffing when they get told
// a generic content type. This is bad, so assume we cannot send
// the file inline.
//
return false;
}
final RepositoryConfig cfg = server.getGerritConfig();
final boolean any = isSafe(cfg, "*/*", false);
final boolean genericMedia = isSafe(cfg, type.getMediaType() + "/*", any);
return isSafe(cfg, type.toString(), genericMedia);
}
private static boolean isSafe(RepositoryConfig cfg, String type, boolean def) {
return cfg.getBoolean(SECTION_MIMETYPE, type, KEY_SAFE, def);
}
private static boolean isUnknownType(Collection<MimeType> mimeTypes) {
if (mimeTypes.isEmpty()) {
return true;
}
return mimeTypes.size() == 1
&& mimeTypes.contains(MimeUtil2.UNKNOWN_MIME_TYPE);
}
}