Данный блог, является записной книжкой. По работе приходится узнавать новые технологии, проводить тесты и сравнения, для хранения результатов решил создать данный блог дабы здесь выкладывать все свои находки и раскопки :)
пятница, 19 октября 2012 г.
понедельник, 15 октября 2012 г.
Полезная команда для выявления нежелательных процессов в Linux
lsof -Pni | grep -vE ':80|:22|named|dovecot|sendm|minis|mysql|pure|pop3|smtp'
Благодаря такому запросу выследил трояна на серваке
пятница, 20 июля 2012 г.
Чтение файла SolidWorks
В продолжение предыдущих статей про SolidWorks...
P.S.: В предыдущих статьях я описывал как
можно просмотреть иерархию файла и пытался извлечь дерево материалов изделия.
Для получения дерева материалов я использовал неверный подход.
Задача:
прочитать фаил сохранений SolidWorks и получить информацию с описанием изделия
и деревом материалов.
Для реализации я использую
- Java 1.7
- Apache POI 3.8
- dom4j
Данный пост я разобью на 3 шага:
- Чтение файла, поиск доступных данных
- Получение необходимых данных
- Получение дерева материалов в формате XML
Шаг 1. Чтение файла, поиск доступных данных
Для чтение файла я использую такой код
FileInputStream fis = new FileInputStream(new File(path));В результате чего я получаю Root каталог внутренней структуры файла, как правило это объект DirectoryNode. В нутрии фаил содержит иерархию в которой хранится информация по изделию
POIFSFileSystem poifsFileSystem = new POIFSFileSystem(fis);
fis.close();
return poifsFileSystem.getRoot();
Дерево в внутри файла состоит из DirectoryNode и DocumentNode объектов.
После получения корневого элемента, нам необходимо просмотреть иерархую, дабы узнать где искать необходимою информацию. Прочитать иерархию можно с помощью данного кода:
public void readNodeAndWriteToConsoleContains(DirectoryNode node) {
Iteratoriterator = node.getEntries();
readIterator(iterator);
}
private void readIterator(Iteratoriterator) {
while (iterator.hasNext()) {
readNode(iterator.next());
}
}
private void readNode(Entry node) {
if (node.isDocumentEntry()) {
System.out.println(" == Directory name: " + node.getParent().getName() + " -- Document: " + node.getName());
}
if (node.isDirectoryEntry()) {
System.out.println("");
System.out.println(" == Directory name: " + node.getName());
readIterator(((DirectoryNode) node).getEntries());
System.out.println("");
}
}
В результате работы кода мы получим что то подобное:
== Directory name: Root Entry -- Document: Config-0-PropertiesКак правило вся вспомогательная информация по изделию размещается в DocumentSummaryInformation и SummaryInformation.
== Directory name: Root Entry -- Document: ISolidWorksInformation
== Directory name: Root Entry -- Document: DocumentSummaryInformation
== Directory name: swXmlContents
== Directory name: swXmlContents -- Document: MATERIALTREE
== Directory name: swXmlContents -- Document: KeyWords__ZLB
== Directory name: swXmlContents -- Document: Tables__ZLB
Шаг 2. Получение необходимых данных
Для начала нам необходимо получить основную информацию, в моем случае это:
- Наименование;
- Обозначение;
- Инвентарный номер документа.
Поля подобные SummaryInformation в нутрии себя хранят лист PropertySet в котором есть вся необходимая информация.
PropertySet summaryInformation = readDocumentNode.read(poifsFileSystem, DocumentSummaryInformation.DEFAULT_STREAM_NAME);
в нутрии метод read выглядит так:
public PropertySet read(POIFSFileSystem poifsFileSystem, String nameDocument) throws IOException {
PropertySet ps = null;
DocumentInputStream dis = poifsFileSystem.createDocumentInputStream(nameDocument);
try {
ps = new PropertySet(dis);
} catch (NoPropertySetStreamException e) {
e.printStackTrace();
} catch (MarkUnsupportedException e) {
e.printStackTrace();
} finally {
dis.close();
}
return ps;
}
читаем PropertySet:
public Listread(PropertySet propertySet, String docName) {
Listresult = new ArrayList ();
PropertyEntry propertyEntry;
for (Section section : propertySet.getSections()) {
Mapobjects = section.getDictionary();
Property[] properties = section.getProperties();
Property property;
for (int i = 0; i < objects.size(); i++) {
property = properties[i];
propertyEntry = new PropertyEntry();
propertyEntry.setKey(objects.get(property.getID()));
propertyEntry.setValue(property.getValue().toString());
propertyEntry.setIndex(i);
propertyEntry.setType(property.getType());
propertyEntry.setDocumentName(docName);
result.add(propertyEntry);
}
}
return result;
}
в результате чего получаем примерно следующие:
DocumentSummaryInformation / Наименование / Какойто чертеж
DocumentSummaryInformation / Обозначение / 87514567
DocumentSummaryInformation / Инвентарный номер документа / 221673
DocumentSummaryInformation / Формат / А4
... прочие данные ...
Шаг 3. Получение дерева материалов в формате XML
Замечательно, мы получили все нужные нам данные, теперь для полноты данных, необходимо получить дерево материалов из которых состоит изделие. Для этого мне надо в Директории файла swXmlContents, прочитать документ MATERIALTREE, данные в котором лежат в формате xml. Задачка простая, делаю это с помощью данного кода:
получаю корневой элемент дерева и перехожу в swXmlContents:
DirectoryNode swXmlContentsDir = (DirectoryNode) poifsFileSystem.getRoot().getEntry("swXmlContents");
после чего читаю документ MATERIALTREE:
DocumentInputStream dis = readDocumentNode.getDocumentInputStream(swXmlContentsDir, "MATERIALTREE");
SAXReader reader = new SAXReader();getDocumentInputStream возвращает имплементацию InputStream из которой я могу прочитать поток данных, в моем случаем это данные в формате XML который я сразу читаю dom4j.
Document document = reader.read(dis);
Заключение:
Спасибо за помощь Streamdown, пост в блоге "Необычная работа с документами solidworks".
Документация и примеры по работе с Apache POI
воскресенье, 15 июля 2012 г.
Чтение структуры файла SolidWorks 2007
Простецкий алгоритм для чтения структуры файла SolidWorks 2007
private void moveIter(Iterator iterator, String name) {
while (iterator.hasNext()) {
def it = iterator.next()
if (it instanceof DocumentNode) {
readDocumentNode(it, name)
}
if (it instanceof DirectoryNode) {
DirectoryNode dn = (DirectoryNode) it
String path = createPath(dn)
moveIter(dn.entries, path)
}
}
}
private def readDocumentNode(DocumentNode documentNode, String path) {
log.error('==-' + documentNode.name + path)
}
private String createPath(DirectoryEntry directoryEntry) {
String result = ''
if (directoryEntry.parent) {
result = createPath(directoryEntry.parent)
}
result = result + '/' + directoryEntry.name
result
}
В результате чего я получил такой список:
- \005 DocumentSummaryInformation
- \005SummaryInformation
- Config-0-Properties
- Header2
- ISolidWorksInformation
- ModelStamps
- Preview
- PreviewPNG
директория Contents
- Config-0
- CMgrHdr2
- eModelLic
- Config-0-GhostPartition
- CnfgObjs
- CMgr
- OleItems
- Config-0-LWDATA
- Config-0-Partition
- DisplayLists__ZLB
- Definition
директория ThirdPty
- MOLDFLOWXpress
- Pw2StorageStream.1.35
- Intermech_internal_structure
- CM_MOTION_LOAD_1
- Intermech_document_settings
- CMMotionLoadMapU
- PBPDFlt
- SWA_Schedules
- Animator__ZLB
директория ThirdPtyStore
- VisualStates__ZLB
- VisualStates_DisplayPane
директория _DL_VERSION_4400
- DLUpdateStamp
- History
- Biography
- AssyVisualData
директория swXmlContents
- Tables__ZLB
- KeyWords__ZLB
- MATERIALTREE
Интересно, что в файле есть такие поля как Intermech, видимо они остаются если у вас в SolideWorks-е подключен плагин Intermech
суббота, 14 июля 2012 г.
Разбор файла чертежа из SolidWorks 2007 и выше (заметки по MATERIALTREE)
Доброго времени суток.
Данный подход был не верен, так как выполняя код:
Чтение дерева материалов из файла описано в данном посте Чтение файла SolidWorks
Старая версия поста:
Заказчик поставил задачу получать информацию из загруженных на сервер файлов чертежей SolidWorks.
Сделал предварительный обзор файлов SolidWorks, я выявил что они файлы
базируются на OLE2. Для работы с данным форматом файлов я использую http://poi.apache.org/
На сайте poi apache есть простые примерчы как можно порчитать иформацию из файла.
При изучении содержимого файла, я натснулся на поле с именем "MATERIALTREE", мне зажотелось получить данные из этого поля, но тут то и были грабли....
Для начала, я не смог обратится простым способом так как DocumentInputStream и PropertySet мне отвечали NoPropertySetStreamException. Я нащел альтернативный подход к данному свойству:
В результате мы получаем объект POIFSDocument который в себе содержет HexDump.
При разборе данного Hex-а:
Object[] objs = doc.getViewableArray()
Hex.decode(objs[0].toString())
Я получил примерно следующие:
Потратив на разбор некоторое время, я наткнулся на сайт http://open-file.ru/, где по hex заголовку удалось выяснить данный hex может относится к :
....
пока это все наблюдения по разбору POIFSDocument "MATERIALTREE"
to be continued...
Данный подход был не верен, так как выполняя код:
POIFSDocument doc = new POIFSDocument("MATERIALTREE", new FileInputStream(file))я всегда получал сам файл, по это причине я его не мог раскрыть.
Чтение дерева материалов из файла описано в данном посте Чтение файла SolidWorks
Старая версия поста:
POIFSDocument doc = new POIFSDocument("MATERIALTREE", new FileInputStream(file))
00000000 D0 CF 11 E0 A1 B1 1A E1 00 00 00 00 00 00 00 00 ................
00000010 00 00 00 00 00 00 00 00 3E 00 03 00 FE FF 09 00 ........>.......
00000020 06 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 ................
00000030 02 00 00 00 00 00 00 00 00 10 00 00 58 01 00 00 ............X...
00000040 03 00 00 00 FE FF FF FF 00 00 00 00 03 00 00 00
Ярлыки:
APACHE POI,
JAVA,
MATERIALTREE,
POIFSDocument,
SOLIDWORKS
пятница, 8 июня 2012 г.
Формат ответа сервиса в зависимости от запроса
Бывает необходимость в том что сервис возвращает разные результаты (xml, json, html) по одному адресу в зависимости от запроса.
- Filters. В данной реализации необходимо наличия content-type в заголовке запроса;
- AfterInterceptor. Реализация данного подхода возможна в случаях если у вас в Config.groovy включена опция grails.mime.file.extensions = true.
Рассмотрим оба подхода.
Первый способ реализовать данную задачу с использованием фильтров. (http://grails.org/doc/latest/guide/single.html#filters). Подход позволяет пользоваться всеми прелестями Filtres в Grails. Реализуется данный подход через Content-type, что обязывает всегда указывать Content-Type, Grails распарсивает то что приходит в запросе и помещает content-type в переменную format, объекта request.
class DetectFormatFilters {
def filters = {
all(action: '*') {
after = { Map model ->
switch (request.format) {
case 'html': println 'return HTML'; break;
case 'json': println 'return JSON'; break;
case 'xml': println 'return XML'; break;
}
}
}
}
}
P.S.: Типы указываются в Grails в config.groovy :
grails.mime.types = [ html: ['text/html','application/xhtml+xml'],
xml: ['text/xml', 'application/xml'],
text: 'text/plain',
js: 'text/javascript',
rss: 'application/rss+xml',
atom: 'application/atom+xml',
css: 'text/css',
csv: 'text/csv',
all: '*/*',
json: ['application/json','text/json'],
form: 'application/x-www-form-urlencoded',
multipartForm: 'multipart/form-data'
]
Второй подход заключается в использовании интерсепротов внутри controller.
(http://grails.org/doc/latest/ref/Controllers/afterInterceptor.html)Данный вариант позволяет использовать несколько вариантов запроса:
- domain/Controller/action/.json, domain/Controller/action/.xml. Данный вариант работает в случае если настройка grails.mime.file.extensions установлена в true;
- domain/Controller/action/?format=json, domain/Controller/action/?format=xml.
def afterInterceptor = {
withFormat {
html {println 'return HTML-1'}
json {println 'return JSON-1'}
js { println "alert('hello')-1" }
xml { println 'return XML-1' }
}
}
withFormat позволяет перечислить типы ответа которые нам необходимы, если тип ответа не обнаружен в списке то будет взят первый пункт, рекомендуется первым пунктом указывать html.
четверг, 31 мая 2012 г.
Batch updates в Grails с использованием HQL
ScrollableResults scroll = getSession()
.createQuery("SELECT DISTINCT t FROM ${tableName} as t LEFT JOIN t.tags as tags WHERE tags.id in (:tags)")
.setParameterList("tags", [oldTag1.id, oldTag2.id])
.scroll(ScrollMode.FORWARD_ONLY)
int count = 0;
while (scroll.next()) {
def exp = scroll.get(0)
exp.tags.remove(oldTag1)
exp.tags.remove(oldTag2)
exp.tags.add(newTag)
exp.save()
if (++count % 20 == 0)
{
session.flush();
session.clear();
}
}
Для работы данного когда надо получить CurrentSession из SessionFactory.
Данный код выполняет HQL запрос и когда число строк обработанных в результате запроса без остатка делится на 20 то сессия хибернейта выполняет flush и clean, что позволяет не загружать память при больших запросах.
Подписаться на:
Сообщения (Atom)