LDIFViewEntryPanel.java revision e1cd6c2bc4addf80537e31f929118ac8f908ea63
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* or http://forgerock.org/license/CDDLv1.0.html.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2008-2010 Sun Microsystems, Inc.
* Portions Copyright 2012-2015 ForgeRock AS
*/
package org.opends.guitools.controlpanel.ui;
import static org.opends.messages.AdminToolMessages.*;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.Point;
import java.io.IOException;
import java.io.StringReader;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.tree.TreePath;
import org.forgerock.i18n.LocalizableMessage;
import org.opends.guitools.controlpanel.datamodel.CustomSearchResult;
import org.opends.guitools.controlpanel.task.OfflineUpdateException;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.server.types.Entry;
import org.opends.server.types.LDIFImportConfig;
import org.opends.server.types.OpenDsException;
import org.opends.server.util.Base64;
import org.opends.server.util.LDIFReader;
import org.opends.server.util.StaticUtils;
/**
* The panel displaying an LDIF view of an entry.
*/
public class LDIFViewEntryPanel extends ViewEntryPanel
{
/** Callback that sets the viewport's view position. */
private static final class SetViewPosition implements Runnable
{
private final Point p;
private final JScrollPane scroll;
private SetViewPosition(JScrollPane scroll, Point p)
{
this.p = p;
this.scroll = scroll;
}
/** {@inheritDoc} */
@Override
public void run()
{
if (p != null && scroll.getViewport().contains(p))
{
scroll.getViewport().setViewPosition(p);
}
}
}
private static final long serialVersionUID = 2775960608128921072L;
private JScrollPane editableScroll;
private JScrollPane readOnlyScroll;
private JTextArea editableAttributes;
private JTextArea readOnlyAttributes;
private CustomSearchResult searchResult;
/** Default constructor. */
public LDIFViewEntryPanel()
{
createLayout();
}
/** {@inheritDoc} */
@Override
public Component getPreferredFocusComponent()
{
return editableAttributes;
}
/**
* Creates the layout of the panel (but the contents are not populated here).
*/
private void createLayout()
{
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 1;
gbc.fill = GridBagConstraints.NONE;
gbc.anchor = GridBagConstraints.WEST;
gbc.weightx = 1.0;
addTitlePanel(this, gbc);
gbc.gridy ++;
gbc.insets.top = 10;
editableAttributes = Utilities.createTextArea(LocalizableMessage.EMPTY, 20, 30);
editableAttributes.getDocument().addDocumentListener(new DocumentListener()
{
@Override
public void insertUpdate(DocumentEvent ev)
{
notifyListeners();
}
@Override
public void changedUpdate(DocumentEvent ev)
{
notifyListeners();
}
@Override
public void removeUpdate(DocumentEvent ev)
{
notifyListeners();
}
});
gbc.weighty = 0.6;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridy ++;
editableScroll = Utilities.createScrollPane(editableAttributes);
add(editableScroll, gbc);
gbc.weighty = 0.0;
gbc.insets.top = 10;
JLabel lReadOnly = Utilities.createPrimaryLabel(
INFO_CTRL_PANEL_NON_EDITABLE_ATTRIBUTES.get());
gbc.gridy ++;
add(lReadOnly, gbc);
gbc.insets.top = 5;
readOnlyAttributes = Utilities.createNonEditableTextArea(LocalizableMessage.EMPTY, 10, 30);
gbc.weightx = 1.0;
gbc.weighty = 0.4;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridy ++;
readOnlyScroll = Utilities.createScrollPane(readOnlyAttributes);
add(readOnlyScroll, gbc);
}
/** {@inheritDoc} */
@Override
public void update(CustomSearchResult sr, boolean isReadOnly, TreePath path)
{
boolean sameEntry = false;
if (searchResult != null && sr != null)
{
sameEntry = searchResult.getDN().equals(sr.getDN());
}
searchResult = sr;
updateTitle(sr, path);
StringBuilder sb = new StringBuilder();
sb.append("dn: ").append(sr.getDN());
if (isReadOnly)
{
editableScroll.setVisible(false);
for (String attrName : sr.getAttributeNames())
{
List<Object> values = sr.getAttributeValues(attrName);
for (Object o : values)
{
sb.append("\n").append(getLDIFLine(attrName, o));
}
}
final Point p1 = sameEntry ?
readOnlyScroll.getViewport().getViewPosition() : new Point(0, 0);
readOnlyAttributes.setText(sb.toString());
SwingUtilities.invokeLater(new SetViewPosition(readOnlyScroll, p1));
}
else
{
editableScroll.setVisible(true);
for (String attrName : sr.getAttributeNames())
{
if (!schemaReadOnlyAttributesLowerCase.contains(attrName.toLowerCase()))
{
List<Object> values = sr.getAttributeValues(attrName);
for (Object o : values)
{
sb.append("\n").append(getLDIFLine(attrName, o));
}
}
}
final Point p1 = sameEntry ?
editableScroll.getViewport().getViewPosition() : new Point(0, 0);
ignoreEntryChangeEvents = true;
editableAttributes.setText(sb.toString());
ignoreEntryChangeEvents = false;
SwingUtilities.invokeLater(new SetViewPosition(editableScroll, p1));
// Read-only attributes
boolean oneLineAdded = false;
sb = new StringBuilder();
for (String attrName : schemaReadOnlyAttributes)
{
List<Object> values = sr.getAttributeValues(attrName);
for (Object o : values)
{
if (oneLineAdded)
{
sb.append("\n");
}
oneLineAdded = true;
sb.append(getLDIFLine(attrName, o));
}
}
final Point p2 = sameEntry ?
readOnlyScroll.getViewport().getViewPosition() : new Point(0, 0);
readOnlyAttributes.setText(sb.toString());
SwingUtilities.invokeLater(new SetViewPosition(readOnlyScroll, p2));
}
}
/** {@inheritDoc} */
@Override
public GenericDialog.ButtonType getButtonType()
{
return GenericDialog.ButtonType.NO_BUTTON;
}
/** {@inheritDoc} */
@Override
protected String getDisplayedDN()
{
String dn = null;
// Do it fast, this is called to update the dn displayed in the title.
String ldif = getLDIF();
int index = ldif.toLowerCase().indexOf("dn: ");
if (index != -1)
{
int index2 = ldif.indexOf("\n", index);
if (index2 != -1)
{
dn = ldif.substring(index + 3, index2).trim();
}
}
return dn;
}
/** {@inheritDoc} */
@Override
protected List<Object> getValues(String attrName)
{
throw new IllegalStateException("This method should not be called.");
}
/** {@inheritDoc} */
@Override
public Entry getEntry() throws OpenDsException
{
LDIFImportConfig ldifImportConfig = null;
try
{
String ldif = getLDIF();
ldifImportConfig = new LDIFImportConfig(new StringReader(ldif));
LDIFReader reader = new LDIFReader(ldifImportConfig);
Entry entry = reader.readEntry(checkSchema());
addValuesInRDN(entry);
return entry;
}
catch (IOException ioe)
{
throw new OfflineUpdateException(
ERR_CTRL_PANEL_ERROR_CHECKING_ENTRY.get(ioe), ioe);
}
finally
{
if (ldifImportConfig != null)
{
ldifImportConfig.close();
}
}
}
/**
* Returns the LDIF representation of the entry, only returns the editable
* attributes.
* @return the LDIF representation of the entry.
*/
private String getLDIF()
{
return editableAttributes.getText();
}
/**
* Returns the equivalent LDIF line for a given attribute and value.
* @param attrName the attribute name.
* @param o the value.
* @return the equivalent LDIF line for the provided attribute and value.
*/
private String getLDIFLine(String attrName, Object o)
{
String attrValue;
if (o instanceof String)
{
if (Utilities.hasControlCharaters((String)o))
{
attrValue = Base64.encode(StaticUtils.getBytes((String)o));
attrName = attrName+":";
}
else
{
attrValue = (String)o;
}
}
else if (o instanceof byte[])
{
attrValue = Base64.encode((byte[])o);
// To indicate that is base64 encoded
attrName = attrName+":";
}
else
{
attrValue = String.valueOf(o);
}
return attrName+": "+ attrValue;
}
}