*/
package jalview.gui;
+import java.awt.Rectangle;
+import java.io.BufferedReader;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarOutputStream;
+
+import javax.swing.JInternalFrame;
+import javax.swing.JOptionPane;
+import javax.swing.SwingUtilities;
+
+import org.exolab.castor.xml.Marshaller;
+import org.exolab.castor.xml.Unmarshaller;
+
import jalview.api.structures.JalviewStructureDisplayI;
import jalview.bin.Cache;
import jalview.datamodel.AlignedCodonFrame;
import jalview.datamodel.SequenceI;
import jalview.datamodel.StructureViewerModel;
import jalview.datamodel.StructureViewerModel.StructureData;
+import jalview.gui.StructureViewer.ViewerType;
import jalview.schemabinding.version2.AlcodMap;
import jalview.schemabinding.version2.AlcodonFrame;
import jalview.schemabinding.version2.Annotation;
import jalview.ws.params.AutoCalcSetting;
import jalview.ws.params.WsParamSetI;
-import java.awt.Rectangle;
-import java.io.BufferedReader;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.lang.reflect.InvocationTargetException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.Vector;
-import java.util.jar.JarEntry;
-import java.util.jar.JarInputStream;
-import java.util.jar.JarOutputStream;
-
-import javax.swing.JInternalFrame;
-import javax.swing.JOptionPane;
-import javax.swing.SwingUtilities;
-
-import org.exolab.castor.xml.Unmarshaller;
-
/**
* Write out the current jalview desktop state as a Jalview XML stream.
*
*/
public class Jalview2XML
{
+ private static final String UTF_8 = "UTF-8";
+
/*
* SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
* of sequence objects are created.
// NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
// //////////////////////////////////////////////////
- Vector shortNames = new Vector();
+ List<String> shortNames = new ArrayList<String>();
// REVERSE ORDER
for (int i = frames.length - 1; i > -1; i--)
continue;
}
- String shortName = af.getTitle();
-
- if (shortName.indexOf(File.separatorChar) > -1)
- {
- shortName = shortName.substring(shortName
- .lastIndexOf(File.separatorChar) + 1);
- }
-
- int count = 1;
-
- while (shortNames.contains(shortName))
- {
- if (shortName.endsWith("_" + (count - 1)))
- {
- shortName = shortName.substring(0, shortName.lastIndexOf("_"));
- }
-
- shortName = shortName.concat("_" + count);
- count++;
- }
-
- shortNames.addElement(shortName);
-
- if (!shortName.endsWith(".xml"))
- {
- shortName = shortName + ".xml";
- }
+ String shortName = makeFilename(af, shortNames);
int ap, apSize = af.alignPanels.size();
}
}
+ /**
+ * Generates a distinct file name, based on the title of the AlignFrame, by
+ * appending _n for increasing n until an unused name is generated. The new
+ * name (without its extension) is added to the list.
+ *
+ * @param af
+ * @param namesUsed
+ * @return the generated name, with .xml extension
+ */
+ protected String makeFilename(AlignFrame af, List<String> namesUsed)
+ {
+ String shortName = af.getTitle();
+
+ if (shortName.indexOf(File.separatorChar) > -1)
+ {
+ shortName = shortName.substring(shortName
+ .lastIndexOf(File.separatorChar) + 1);
+ }
+
+ int count = 1;
+
+ while (namesUsed.contains(shortName))
+ {
+ if (shortName.endsWith("_" + (count - 1)))
+ {
+ shortName = shortName.substring(0, shortName.lastIndexOf("_"));
+ }
+
+ shortName = shortName.concat("_" + count);
+ count++;
+ }
+
+ namesUsed.add(shortName);
+
+ if (!shortName.endsWith(".xml"))
+ {
+ shortName = shortName + ".xml";
+ }
+ return shortName;
+ }
+
// USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
public boolean saveAlignment(AlignFrame af, String jarFile,
String fileName)
jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
.nextElement();
- pdb.setId(entry.getId());
+ String pdbId = entry.getId();
+ pdb.setId(pdbId);
pdb.setType(entry.getType());
/*
StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
matchedFile = saveStructureState(ap, jds, pdb, entry,
viewIds, matchedFile, viewFrame);
+ /*
+ * Only store each structure viewer's state once in each XML
+ * document. First time through only (storeDS==false)
+ */
+ String viewId = viewFrame.getViewId();
+ if (!storeDS && !viewIds.contains(viewId))
+ {
+ viewIds.add(viewId);
+ try
+ {
+ writeJarEntry(jout, "viewer_" + viewId,
+ viewFrame.getStateInfo().getBytes());
+ } catch (IOException e)
+ {
+ System.err.println("Error saving viewer state: "
+ + e.getMessage());
+ }
+ }
}
}
pdbfiles = new ArrayList<String>();
}
- if (!pdbfiles.contains(entry.getId()))
+ if (!pdbfiles.contains(pdbId))
{
- pdbfiles.add(entry.getId());
- DataInputStream dis = null;
- try
- {
- File file = new File(matchedFile);
- if (file.exists() && jout != null)
- {
- byte[] data = new byte[(int) file.length()];
- jout.putNextEntry(new JarEntry(entry.getId()));
- dis = new DataInputStream(new FileInputStream(file));
- dis.readFully(data);
-
- DataOutputStream dout = new DataOutputStream(jout);
- dout.write(data, 0, data.length);
- dout.flush();
- jout.closeEntry();
- }
- } catch (Exception ex)
- {
- ex.printStackTrace();
- } finally
- {
- if (dis != null)
- {
- try
- {
- dis.close();
- } catch (IOException e)
- {
- // ignore
- }
- }
- }
-
+ pdbfiles.add(pdbId);
+ copyFileToJar(jout, matchedFile, pdbId);
}
}
- if (entry.getProperty() != null)
+ if (entry.getProperty() != null && !entry.getProperty().isEmpty())
{
PdbentryItem item = new PdbentryItem();
Hashtable properties = entry.getProperty();
}
}
}
+
+ /*
+ * Save associated Varna panels
+ */
+ if (Desktop.desktop != null)
+ {
+ for (JInternalFrame frame : Desktop.desktop.getAllFrames())
+ {
+ if (frame instanceof AppVarna)
+ {
+ AppVarna vp = (AppVarna) frame;
+ if (vp.ap == ap)
+ {
+ // save Varna state
+ }
+ }
+ }
+ }
+
// SAVE ANNOTATIONS
/**
* store forward refs from an annotationRow to any groups
JarEntry entry = new JarEntry(fileName);
jout.putNextEntry(entry);
PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
- "UTF-8"));
- org.exolab.castor.xml.Marshaller marshaller = new org.exolab.castor.xml.Marshaller(
- pout);
+ UTF_8));
+ Marshaller marshaller = new Marshaller(pout);
marshaller.marshal(object);
pout.flush();
jout.closeEntry();
}
/**
+ * Copy the contents of a file to a new file added to the output jar
+ *
+ * @param jout
+ * @param infilePath
+ * @param jarfileName
+ */
+ protected void copyFileToJar(JarOutputStream jout, String infilePath,
+ String jarfileName)
+ {
+ DataInputStream dis = null;
+ try
+ {
+ File file = new File(infilePath);
+ if (file.exists() && jout != null)
+ {
+ dis = new DataInputStream(new FileInputStream(file));
+ byte[] data = new byte[(int) file.length()];
+ dis.readFully(data);
+ writeJarEntry(jout, jarfileName, data);
+ }
+ } catch (Exception ex)
+ {
+ ex.printStackTrace();
+ } finally
+ {
+ if (dis != null)
+ {
+ try
+ {
+ dis.close();
+ } catch (IOException e)
+ {
+ // ignore
+ }
+ }
+ }
+ }
+
+ /**
+ * Write the data to a new entry of given name in the output jar file
+ *
+ * @param jout
+ * @param jarfileName
+ * @param data
+ * @throws IOException
+ */
+ protected void writeJarEntry(JarOutputStream jout, String jarfileName,
+ byte[] data) throws IOException
+ {
+ if (jout != null)
+ {
+ jout.putNextEntry(new JarEntry(jarfileName));
+ DataOutputStream dout = new DataOutputStream(jout);
+ dout.write(data, 0, data.length);
+ dout.flush();
+ jout.closeEntry();
+ }
+ }
+
+ /**
* Save the state of a structure viewer
*
* @param ap
String matchedFile, StructureViewerBase viewFrame)
{
final AAStructureBindingModel bindingModel = viewFrame.getBinding();
+
+ /*
+ * Look for any bindings for this viewer to the PDB file of interest
+ * (including part matches excluding chain id)
+ */
for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
{
final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
&& !(entry.getId().length() > 4 && entry.getId()
.toLowerCase().startsWith(pdbId.toLowerCase())))
{
+ /*
+ * not interested in a binding to a different PDB entry here
+ */
continue;
}
if (matchedFile == null)
// can get at it if the ID
// match is ambiguous (e.g.
// 1QIP==1qipA)
- String statestring = viewFrame.getStateInfo();
for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
{
state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
state.setColourByJmol(viewFrame.isColouredByViewer());
- /*
- * Only store each structure viewer's state once in each XML document.
- */
- if (!viewIds.contains(viewId))
- {
- viewIds.add(viewId);
- state.setContent(statestring.replaceAll("\n", ""));
- }
- else
- {
- state.setContent("# duplicate state");
- }
+ // FIXME add attribute to schema and enable next line
+ // state.setType(viewFrame.getViewerType().toString());
+ state.setContent(viewFrame.getViewerType().toString());
pdb.addStructureState(state);
}
}
if (jarentry != null && jarentry.getName().endsWith(".xml"))
{
- InputStreamReader in = new InputStreamReader(jin, "UTF-8");
+ InputStreamReader in = new InputStreamReader(jin, UTF_8);
JalviewModel object = new JalviewModel();
Unmarshaller unmar = new Unmarshaller(object);
*/
private final boolean updateLocalViews = false;
+ /**
+ * Returns the path to a temporary file holding the PDB file for the given PDB
+ * id. The first time of asking, searches for a file of that name in the
+ * Jalview project jar, and copies it to a new temporary file. Any repeat
+ * requests just return the path to the file previously created.
+ *
+ * @param jprovider
+ * @param pdbId
+ * @return
+ */
String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
{
if (alreadyLoadedPDB.containsKey(pdbId))
return alreadyLoadedPDB.get(pdbId).toString();
}
+ String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb");
+ if (tempFile != null)
+ {
+ alreadyLoadedPDB.put(pdbId, tempFile);
+ }
+ return tempFile;
+ }
+
+ /**
+ * Copies the jar entry of given name to a new temporary file and returns the
+ * path to the file, or null if the entry is not found.
+ *
+ * @param jprovider
+ * @param jarEntryName
+ * @param prefix
+ * a prefix for the temporary file name, must be at least three
+ * characters long
+ * @return
+ */
+ protected String copyJarEntry(jarInputStreamProvider jprovider,
+ String jarEntryName, String prefix)
+ {
+ BufferedReader in = null;
+ PrintWriter out = null;
+
try
{
JarInputStream jin = jprovider.getJarInputStream();
do
{
entry = jin.getNextJarEntry();
- } while (entry != null && !entry.getName().equals(pdbId));
+ } while (entry != null && !entry.getName().equals(jarEntryName));
if (entry != null)
{
- BufferedReader in = new BufferedReader(new InputStreamReader(jin));
- File outFile = File.createTempFile("jalview_pdb", ".txt");
+ in = new BufferedReader(new InputStreamReader(jin, UTF_8));
+ File outFile = File.createTempFile(prefix, ".tmp");
outFile.deleteOnExit();
- PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
+ out = new PrintWriter(new FileOutputStream(outFile));
String data;
while ((data = in.readLine()) != null)
{
out.println(data);
}
- try
- {
- out.flush();
- } catch (Exception foo)
- {
- }
- ;
- out.close();
+ out.flush();
String t = outFile.getAbsolutePath();
- alreadyLoadedPDB.put(pdbId, t);
return t;
}
else
{
- warn("Couldn't find PDB file entry in Jalview Jar for " + pdbId);
+ warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
}
} catch (Exception ex)
{
ex.printStackTrace();
+ } finally
+ {
+ if (in != null)
+ {
+ try
+ {
+ in.close();
+ } catch (IOException e)
+ {
+ // ignore
+ }
+ }
+ if (out != null)
+ {
+ out.close();
+ }
}
return null;
}
if (!structureViewers.containsKey(sviewid))
{
- structureViewers.put(sviewid, new StructureViewerModel(x, y,
- width, height, false, false, true));
+ structureViewers.put(sviewid,
+ new StructureViewerModel(x, y, width, height, false,
+ false, true, structureState.getViewId()));
// Legacy pre-2.7 conversion JAL-823 :
// do not assume any view has to be linked for colour by
// sequence
// Instantiate the associated structure views
for (Entry<String, StructureViewerModel> entry : structureViewers
.entrySet())
+ {
+ try
+ {
+ createOrLinkStructureViewer(entry, af, ap, jprovider);
+ } catch (Exception e)
{
- createOrLinkStructureViewer(entry, af, ap);
+ System.err.println("Error loading structure viewer: "
+ + e.getMessage());
+ // failed - try the next one
+ }
}
}
* @param viewerData
* @param af
* @param ap
+ * @param jprovider
*/
protected void createOrLinkStructureViewer(
Entry<String, StructureViewerModel> viewerData, AlignFrame af,
- AlignmentPanel ap)
+ AlignmentPanel ap, jarInputStreamProvider jprovider)
{
- final StructureViewerModel svattrib = viewerData.getValue();
+ final StructureViewerModel stateData = viewerData.getValue();
/*
* Search for any viewer windows already open from other alignment views
if (comp != null)
{
- linkStructureViewer(ap, comp, svattrib);
+ linkStructureViewer(ap, comp, stateData);
return;
}
/*
- * Pending an XML element for ViewerType, just check if stateData contains
- * "chimera" (part of the chimera session filename).
+ * 2.8.2: stateData contains "chimera..." (session file name), or JMOL state
+ * string
+ *
+ * 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
+ * "viewer_"+stateData.viewId
*/
- if (svattrib.getStateData().indexOf("chimera") > -1)
+ // FIXME use stateData.getType() instead once schema updated
+ if (ViewerType.CHIMERA.toString().equals(stateData.getStateData())
+ || stateData.getStateData().indexOf("chimera") > -1)
{
- createChimeraViewer(viewerData, af);
+ createChimeraViewer(viewerData, af, jprovider);
}
else
{
- createJmolViewer(viewerData, af);
+ createJmolViewer(viewerData, af, jprovider);
}
}
/**
* Create a new Chimera viewer.
*
- * @param viewerData
+ * @param data
* @param af
+ * @param jprovider
*/
- protected void createChimeraViewer(
- Entry<String, StructureViewerModel> viewerData, AlignFrame af)
+ protected void createChimeraViewer(Entry<String, StructureViewerModel> viewerData,
+ AlignFrame af,
+ jarInputStreamProvider jprovider)
{
- final StructureViewerModel data = viewerData.getValue();
- String chimeraSession = data.getStateData();
+ StructureViewerModel data = viewerData.getValue();
+ String chimeraSessionFile = data.getStateData();
- if (new File(chimeraSession).exists())
- {
- Set<Entry<File, StructureData>> fileData = data.getFileData()
- .entrySet();
- List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
- List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
- for (Entry<File, StructureData> pdb : fileData)
- {
- String filePath = pdb.getValue().getFilePath();
- String pdbId = pdb.getValue().getPdbId();
- // pdbs.add(new PDBEntry(filePath, pdbId));
- pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
- final List<SequenceI> seqList = pdb.getValue().getSeqList();
- SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
- allseqs.add(seqs);
- }
-
- boolean colourByChimera = data.isColourByViewer();
- boolean colourBySequence = data.isColourWithAlignPanel();
-
- // TODO can/should this be done via StructureViewer (like Jmol)?
- final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
- final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
- .size()][]);
- new ChimeraViewFrame(chimeraSession, af.alignPanel, pdbArray,
- seqsArray, colourByChimera, colourBySequence);
- }
- else
- {
- Cache.log.error("Chimera session file " + chimeraSession
- + " not found");
- }
+ /*
+ * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
+ *
+ * Note this is the 'saved' viewId as in the project file XML, _not_ the
+ * 'uniquified' sviewid used to reconstruct the viewer here
+ */
+ chimeraSessionFile = copyJarEntry(jprovider,
+ "viewer_" + data.getViewId(), "chimera");
+
+ Set<Entry<File, StructureData>> fileData = data.getFileData()
+ .entrySet();
+ List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
+ List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
+ for (Entry<File, StructureData> pdb : fileData)
+ {
+ String filePath = pdb.getValue().getFilePath();
+ String pdbId = pdb.getValue().getPdbId();
+ // pdbs.add(new PDBEntry(filePath, pdbId));
+ pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
+ final List<SequenceI> seqList = pdb.getValue().getSeqList();
+ SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
+ allseqs.add(seqs);
+ }
+
+ boolean colourByChimera = data.isColourByViewer();
+ boolean colourBySequence = data.isColourWithAlignPanel();
+
+ // TODO use StructureViewer as a factory here, see JAL-1761
+ final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
+ final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
+ .size()][]);
+ String newViewId = viewerData.getKey();
+ new ChimeraViewFrame(chimeraSessionFile, af.alignPanel, pdbArray,
+ seqsArray, colourByChimera, colourBySequence, newViewId);
}
/**
*
* @param viewerData
* @param af
+ * @param jprovider
*/
protected void createJmolViewer(
final Entry<String, StructureViewerModel> viewerData,
- AlignFrame af)
+ AlignFrame af, jarInputStreamProvider jprovider)
{
final StructureViewerModel svattrib = viewerData.getValue();
String state = svattrib.getStateData();
+
+ /*
+ * Pre-2.9: state element value is the Jmol state string
+ *
+ * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
+ * + viewId
+ */
+ // FIXME use getType once Castor regenerated for new attribute
+ if (ViewerType.JMOL.toString().equals(state /* svattrib.getType() */))
+ {
+ state = readJarEntry(jprovider, "viewer_" + svattrib.getViewId());
+ }
+
List<String> pdbfilenames = new ArrayList<String>();
List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
List<String> pdbids = new ArrayList<String>();
JalviewStructureDisplayI sview = null;
try
{
- // JAL-1333 note - we probably can't migrate Jmol views to UCSF
- // Chimera!
sview = new StructureViewer(alf.alignPanel
.getStructureSelectionManager()).createView(
StructureViewer.ViewerType.JMOL, pdbf, id, sq,
&& ((StructureViewerBase) frame).getViewId()
.equals(sviewid))
{
- comp = (AppJmol) frame;
- // todo: break?
+ comp = (StructureViewerBase) frame;
+ break; // break added in 2.9
}
/*
* Otherwise test for matching position and size of viewer frame
&& frame.getHeight() == svattrib.getHeight()
&& frame.getWidth() == svattrib.getWidth())
{
- comp = (AppJmol) frame;
- // todo: break?
+ comp = (StructureViewerBase) frame;
+ // no break in faint hope of an exact match on viewId
}
}
}
* @param viewerColouring
*/
protected void linkStructureViewer(AlignmentPanel ap,
- StructureViewerBase viewer, StructureViewerModel svattrib)
+ StructureViewerBase viewer, StructureViewerModel stateData)
{
// NOTE: if the jalview project is part of a shared session then
// view synchronization should/could be done here.
- final boolean useinViewerSuperpos = svattrib.isAlignWithPanel();
- final boolean usetoColourbyseq = svattrib.isColourWithAlignPanel();
- final boolean viewerColouring = svattrib.isColourByViewer();
- Map<File, StructureData> oldFiles = svattrib.getFileData();
+ final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
+ final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
+ final boolean viewerColouring = stateData.isColourByViewer();
+ Map<File, StructureData> oldFiles = stateData.getFileData();
/*
* Add mapping for sequences in this view to an already open viewer
{
skipList = skipList2;
}
+
+ /**
+ * Reads the jar entry of given name and returns its contents, or null if the
+ * entry is not found.
+ *
+ * @param jprovider
+ * @param jarEntryName
+ * @return
+ */
+ protected String readJarEntry(jarInputStreamProvider jprovider,
+ String jarEntryName)
+ {
+ String result = null;
+ BufferedReader in = null;
+
+ try
+ {
+ /*
+ * Reopen the jar input stream and traverse its entries to find a matching
+ * name
+ */
+ JarInputStream jin = jprovider.getJarInputStream();
+ JarEntry entry = null;
+ do
+ {
+ entry = jin.getNextJarEntry();
+ } while (entry != null && !entry.getName().equals(jarEntryName));
+
+ if (entry != null)
+ {
+ StringBuilder out = new StringBuilder(256);
+ in = new BufferedReader(new InputStreamReader(jin, UTF_8));
+ String data;
+
+ while ((data = in.readLine()) != null)
+ {
+ out.append(data);
+ }
+ result = out.toString();
+ }
+ else
+ {
+ warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
+ }
+ } catch (Exception ex)
+ {
+ ex.printStackTrace();
+ } finally
+ {
+ if (in != null)
+ {
+ try
+ {
+ in.close();
+ } catch (IOException e)
+ {
+ // ignore
+ }
+ }
+ }
+
+ return result;
+ }
}